diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c9be265376..3ff6fda3bc 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Minecraft Version description: What version of Minecraft are you running? If you do not know what version you are using, look in the bottom left corner of the main menu in game. options: + - "26.1" - "1.21.11" - "1.21.9/1.21.10" validations: @@ -44,7 +45,7 @@ body: attributes: label: Skyblocker Version description: What version of Skyblocker are you running? Every part is important! If you do not know what version you are using, look at the file name in your "mods" folder. - placeholder: ex. skyblocker-5.0.0+1.21.11.jar + placeholder: ex. skyblocker-6.0.0+26.1.jar validations: required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/crash_report.yml b/.github/ISSUE_TEMPLATE/crash_report.yml index b99fdc8ed2..89ed2bf20d 100644 --- a/.github/ISSUE_TEMPLATE/crash_report.yml +++ b/.github/ISSUE_TEMPLATE/crash_report.yml @@ -16,6 +16,7 @@ body: label: Minecraft Version description: What version of Minecraft are you running? If you do not know what version you are using, look in the bottom left corner of the main menu in game. options: + - "26.1" - "1.21.11" - "1.21.9/1.21.10" validations: @@ -25,7 +26,7 @@ body: attributes: label: Skyblocker Version description: What version of Skyblocker are you running? Every part is important! If you do not know what version you are using, look at the file name in your "mods" folder. - placeholder: ex. skyblocker-5.0.0+1.21.11.jar + placeholder: ex. skyblocker-6.0.0+26.1.jar validations: required: true - type: textarea @@ -66,10 +67,10 @@ body: at de.hysky.skyblocker.utils.Scheduler.tick(Scheduler.java:76) at de.hysky.skyblocker.SkyblockerMod.tick(SkyblockerMod.java:116) at net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents.lambda$static$2(ClientTickEvents.java:43) - at net.minecraft.class_310.handler$ble000$fabric-lifecycle-events-v1$onEndTick(class_310.java:11022) - at net.minecraft.class_310.method_1574(class_310.java:1957) - at net.minecraft.class_310.method_1523(class_310.java:1181) - at net.minecraft.class_310.method_1514(class_310.java:802) + at net.minecraft.client.Minecraft.handler$ble000$fabric-lifecycle-events-v1$onEndTick(Minecraft.java:11022) + at net.minecraft.client.Minecraft.tick(Minecraft.java:1957) + at net.minecraft.client.Minecraft.runTick(Minecraft.java:1181) + at net.minecraft.client.Minecraft.run(Minecraft.java:802) at net.minecraft.client.main.Main.main(Main.java:250) render: shell - type: textarea diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index 15534d13b7..e5029b4c5d 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -39,10 +39,10 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set jar name - uses: actions/github-script@v7 + uses: actions/github-script@v8 if: ${{ !inputs.skip_modify_version }} with: result-encoding: string @@ -63,20 +63,20 @@ jobs: file = file.toString().split("\n").map(e => e.trim().startsWith("mod_version") ? `${e}-${buildType}-${commitSha.substring(0, 7)}` : e).join("\n"); fs.writeFileSync("./gradle.properties", file); - - name: Set up JDK 21 - uses: actions/setup-java@v4 + - name: Set up JDK 25 + uses: actions/setup-java@v5 with: distribution: 'microsoft' - java-version: '21' + java-version: '25' - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Build with Gradle run: ./gradlew build - name: Store reports if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: reports path: | @@ -84,7 +84,7 @@ jobs: **/build/test-results/ - name: Process artifacts - uses: actions/github-script@v7 + uses: actions/github-script@v8 id: fname with: result-encoding: string @@ -93,7 +93,7 @@ jobs: return fs.readdirSync("build/libs/").filter(e => !e.endsWith("dev.jar") && !e.endsWith("sources.jar") && e.endsWith(".jar"))[0].replace(".jar", ""); - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ steps.fname.outputs.result }} path: build/libs/ @@ -103,21 +103,21 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 - - name: Set up JDK 21 - uses: actions/setup-java@v4 + uses: actions/checkout@v6 + - name: Set up JDK 25 + uses: actions/setup-java@v5 with: distribution: 'microsoft' - java-version: '21' + java-version: '25' - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Run client gametest with Xvfb uses: modmuss50/xvfb-action@v1 with: run: ./gradlew runClientGametest - name: Upload test screenshots - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 if: always() with: name: Test Screenshots diff --git a/.github/workflows/buildrelease.yml b/.github/workflows/buildrelease.yml index f9ff4c9cd1..cc4888185c 100644 --- a/.github/workflows/buildrelease.yml +++ b/.github/workflows/buildrelease.yml @@ -9,20 +9,20 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Set up JDK 21 - uses: actions/setup-java@v4 + - uses: actions/checkout@v6 + - name: Set up JDK 25 + uses: actions/setup-java@v5 with: distribution: 'microsoft' - java-version: '21' + java-version: '25' - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v5 - name: Build with Gradle run: ./gradlew build - name: Process artifacts - uses: actions/github-script@v7 + uses: actions/github-script@v8 id: fname with: result-encoding: string @@ -30,7 +30,7 @@ jobs: const fs = require("fs") return fs.readdirSync("build/libs/").filter(e => !e.endsWith("dev.jar") && !e.endsWith("sources.jar") && e.endsWith(".jar"))[0].replace(".jar", ""); - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: ${{ steps.fname.outputs.result }} path: build/libs/ diff --git a/.github/workflows/webhook_translate.yml b/.github/workflows/webhook_translate.yml index c6cd1d609c..18e470c4c7 100644 --- a/.github/workflows/webhook_translate.yml +++ b/.github/workflows/webhook_translate.yml @@ -13,16 +13,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: '1.20' - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('go.sum') }} diff --git a/.gitignore b/.gitignore index 896dca7fad..9acb82c1ce 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ bin/ # fabric run/ +.fabric/ diff --git a/README.md b/README.md index 87015f2412..c31b405bed 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ \ [![Discord](https://img.shields.io/discord/879732108745125969?logo=discord&labelColor=cecece&color=7289DA&label=)](https://discord.com/invite/aNNJHQykck) -Hypixel Skyblock Mod for Minecraft 1.21.11 +Hypixel Skyblock Mod for Minecraft 26.1 Installation guide is [here](https://github.com/SkyblockerMod/Skyblocker/wiki/installation) or use our [Modpack](https://modrinth.com/modpack/skyblocker-modpack) ## Features diff --git a/build.gradle b/build.gradle index e950ec9904..acc1b0a375 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { // Building - id 'net.fabricmc.fabric-loom-remap' version "${loom_version}" + id 'net.fabricmc.fabric-loom' version "${loom_version}" id "de.hysky.skyblocker.annotation-processor" id "com.diffplug.spotless" version "${spotless_version}" id "checkstyle" @@ -134,45 +134,43 @@ dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings loom.officialMojangMappings() - - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + implementation "net.fabricmc:fabric-loader:${project.loader_version}" // Loom does not always add this implementation "ca.weblite:java-objc-bridge:1.1" // Fabric API - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" + implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" // Dandelion (also shades in MoulConfig) - include modImplementation("net.azureaaron:dandelion:${project.dandelion_version}") + include implementation("net.azureaaron:dandelion:${project.dandelion_version}") // YACL - include modImplementation("dev.isxander:yet-another-config-lib:${project.yacl_version}-fabric") + include implementation("dev.isxander:yet-another-config-lib:${project.yacl_version}-fabric") // HM API (Hypixel Mod API Library) - include modImplementation("net.azureaaron:hm-api:${project.hm_api_version}") + include implementation("net.azureaaron:hm-api:${project.hm_api_version}") // Mod Menu - modImplementation "com.terraformersmc:modmenu:${project.mod_menu_version}" + implementation "com.terraformersmc:modmenu:${project.mod_menu_version}" // REI - modCompileOnly("me.shedaniel:RoughlyEnoughItems-api-fabric:${project.rei_version}") { - exclude group: "net.fabricmc.fabric-api" //Stop this from importing an old version of FAPI that crashes everything - } - //modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}" + //compileOnly("me.shedaniel:RoughlyEnoughItems-api-fabric:${project.rei_version}") { + //exclude group: "net.fabricmc.fabric-api" //Stop this from importing an old version of FAPI that crashes everything + //} + //runtimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}" // EMI - modCompileOnly "dev.emi:emi-fabric:${project.emi_version}:api" - //modLocalRuntime "dev.emi:emi-fabric:${project.emi_version}" + //compileOnly "dev.emi:emi-fabric:${project.emi_version}:api" + //localRuntime "dev.emi:emi-fabric:${project.emi_version}" // JEI (Using modrinth repo since official release is in mojmap and doesn't work) - modCompileOnly "maven.modrinth:jei:${project.jei_version}-fabric" - //modRuntimeOnly "maven.modrinth:jei:${project.jei_version}-fabric" + //compileOnly "maven.modrinth:jei:${project.jei_version}-fabric" + //runtimeOnly "maven.modrinth:jei:${project.jei_version}-fabric" compileOnly "com.demonwav.mcdev:annotations:${project.mcdev_annotations_version}" - include modImplementation("meteordevelopment:discord-ipc:1.1") + include implementation("meteordevelopment:discord-ipc:1.1") // NEU RepoParser include implementation("moe.nea:neurepoparser:${project.repoparser_version}") @@ -193,16 +191,12 @@ dependencies { include implementation("org.apache.commons:commons-text:${project.commons_text_version}") // Fabric Language Kotlin for using MoulConfig - we are still a Java-exclusive mod - modImplementation("net.fabricmc:fabric-language-kotlin:${project.flk_version}") + implementation("net.fabricmc:fabric-language-kotlin:${project.flk_version}") } loom { accessWidenerPath = file("src/main/resources/skyblocker.classtweaker") - mixin { - useLegacyMixinAp = false - } - decompilers { vineflower { options.put( @@ -213,6 +207,16 @@ loom { } } +sourceSets { + main { + java { + exclude("**/compatibility/rei/**") + exclude("**/compatibility/jei/**") + exclude("**/compatibility/emi/**") + } + } +} + fabricApi { configureTests { createSourceSet = true @@ -235,12 +239,13 @@ tasks.withType(ProcessResources).configureEach { } tasks.withType(JavaCompile).configureEach { - it.options.release = 21 + it.options.release = 25 + it.options.compilerArgs << "-Xmaxerrs" << "2000" } java { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } jar { @@ -343,7 +348,7 @@ def truncateChangelog = { String text, int limit -> } publishMods { - file = remapJar.archiveFile + file = jar.archiveFile changelog = System.getenv('CHANGELOG_HIGHLIGHT') version = "v${project.version}" displayName = "Skyblocker ${mod_version} for ${minecraft_version}" diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index c6398c0a0c..3651819a25 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -7,16 +7,23 @@ repositories { } dependencies { - implementation "org.ow2.asm:asm:${project.asm_version}" - implementation "org.ow2.asm:asm-tree:${project.asm_version}" + implementation "org.jspecify:jspecify:${project.jspecify_version}" } gradlePlugin { plugins { simplePlugin { id = 'de.hysky.skyblocker.annotation-processor' - // The plugin entry point could be changed to a different class that then appropriately calls the different processors when there's more than one. implementationClass = 'de.hysky.skyblocker.Processor' } } } + +tasks.withType(JavaCompile).configureEach { + it.options.release = 25 +} + +java { + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 +} diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties index 31ca1b207c..18a5634d5d 100644 --- a/buildSrc/gradle.properties +++ b/buildSrc/gradle.properties @@ -1 +1 @@ -asm_version=9.9 \ No newline at end of file +jspecify_version=1.0.0 \ No newline at end of file diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/ClassReference.java b/buildSrc/src/main/java/de/hysky/skyblocker/ClassReference.java deleted file mode 100644 index ed4b308aa9..0000000000 --- a/buildSrc/src/main/java/de/hysky/skyblocker/ClassReference.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.hysky.skyblocker; - -/** - * Record representing a reference to some class. - * - * @param className The class' name according to {@link Class#getName()} where '.' are replaced with '/' (e.g. 'de.hysky.skyblocker.SkyblockerMod'). - * @param descriptor The class' descriptor (e.g. 'Lde/hysky/skyblocker/SkyblockerMod;'). - */ -public record ClassReference(String className, String descriptor) { - - public ClassReference(String className) { - this(className, "L" + className + ";"); - } -} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/FieldReference.java b/buildSrc/src/main/java/de/hysky/skyblocker/FieldReference.java deleted file mode 100644 index ecdc85186c..0000000000 --- a/buildSrc/src/main/java/de/hysky/skyblocker/FieldReference.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.hysky.skyblocker; - -/** - * Record representing some reference to a field. - * - * @param className The name of the class the field is in. See {@link ClassReference#className()}. - * @param fieldName The name of the field (e.g. 'value'). - * @param descriptor The field's descriptor (e.g. 'Z', 'Ljava/lang/Object;'). - */ -public record FieldReference(String className, String fieldName, String descriptor) { -} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/MethodReference.java b/buildSrc/src/main/java/de/hysky/skyblocker/MethodReference.java deleted file mode 100644 index 6aebbb4ae7..0000000000 --- a/buildSrc/src/main/java/de/hysky/skyblocker/MethodReference.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.hysky.skyblocker; - -/** - * Record representing some reference to a method. - * - * @param className The name of the class the method is in. See {@link ClassReference#className()}. - * @param methodName The name of the method (e.g. 'main'). - * @param descriptor The descriptor of the method (e.g. '(IJ)Z', '(Lnet/java/lang/Long;IZ)Ljava/lang/String;'). - * @param itf Whether this method belongs to an interface. - */ -public record MethodReference(String className, String methodName, String descriptor, boolean itf) { - - public boolean matches(String methodName, String descriptor) { - return this.methodName.equals(methodName) && this.descriptor.equals(descriptor); - } -} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/Pair.java b/buildSrc/src/main/java/de/hysky/skyblocker/Pair.java deleted file mode 100644 index 6eba73cedc..0000000000 --- a/buildSrc/src/main/java/de/hysky/skyblocker/Pair.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.hysky.skyblocker; - -/** - * An immutable pair of values. - */ -public record Pair(T1 left, T2 right) { -} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/Processor.java b/buildSrc/src/main/java/de/hysky/skyblocker/Processor.java index 909ffe14f0..4520584e05 100644 --- a/buildSrc/src/main/java/de/hysky/skyblocker/Processor.java +++ b/buildSrc/src/main/java/de/hysky/skyblocker/Processor.java @@ -1,70 +1,158 @@ package de.hysky.skyblocker; -import de.hysky.skyblocker.hud.HudProcessor; -import de.hysky.skyblocker.init.InitProcessor; -import de.hysky.skyblocker.object.ObjectProcessor; - -import org.gradle.api.Plugin; -import org.gradle.api.Project; -import org.gradle.api.logging.Logger; -import org.gradle.api.logging.Logging; -import org.gradle.api.tasks.compile.JavaCompile; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; - import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassFile.ClassHierarchyResolverOption; +import java.lang.classfile.ClassHierarchyResolver; +import java.lang.classfile.ClassModel; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; +import java.lang.reflect.AccessFlag; +import java.net.URL; +import java.net.URLClassLoader; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.Consumer; -import java.util.function.Function; -public class Processor implements Plugin { +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.logging.Logger; +import org.gradle.api.logging.Logging; +import org.gradle.api.tasks.compile.JavaCompile; +import org.jspecify.annotations.Nullable; - public static final Logger logger = Logging.getLogger(Processor.class); - public static File classesDir; +import de.hysky.skyblocker.hud.HudProcessor; +import de.hysky.skyblocker.init.InitProcessor; +import de.hysky.skyblocker.object.ObjectProcessor; + +public class Processor implements Plugin { + public static final Logger LOGGER = Logging.getLogger(Processor.class); + public static @Nullable File classesDir; + public static @Nullable URLClassLoader compileClasspathLoader; @Override - public void apply(@NotNull Project project) { + public void apply(Project project) { // https://docs.gradle.org/current/userguide/task_configuration_avoidance.html // This only configures the `compileJava` task and not other `JavaCompile` tasks such as `compileTestJava`. https://stackoverflow.com/a/77047012 project.getTasks().withType(JavaCompile.class).named("compileJava").get().doLast(task -> { JavaCompile javaCompile = (JavaCompile) task; classesDir = javaCompile.getDestinationDirectory().get().getAsFile(); - new InitProcessor().apply(javaCompile); - new HudProcessor().apply(javaCompile); - ObjectProcessor.apply(); + // Used for quickly extracting information from the mod's classes (so we don't reparse them a bunch of times) + // NB: These class models MUST NOT be used when injecting into the class otherwise transformations will not stack!!! + Map skyblockerClasses = readSkyblockerClasses(); + + // The ClassFile API needs the complete hierarchy of classes in use to construct correct bytecode, so we + // create the appropriate resolvers that provide such information. + ClassHierarchyResolver skyblockerClassHierarchyResolver = skyblockerClassHierarchyResolver(skyblockerClasses); + ClassHierarchyResolver compileClassPathHierarchyResolver = compileClasspathHierarchyResolver(javaCompile); + ClassHierarchyResolver completeClassHierarchyResolver = skyblockerClassHierarchyResolver + .orElse(compileClassPathHierarchyResolver) + .orElse(ClassHierarchyResolver.defaultResolver()); + ClassFile context = ClassFile.of(ClassHierarchyResolverOption.of(completeClassHierarchyResolver)); + + // Apply processors + InitProcessor.apply(context, skyblockerClasses); + ObjectProcessor.apply(context, skyblockerClasses); + HudProcessor.apply(context, skyblockerClasses); + + // Close URL class loader + if (compileClasspathLoader != null) { + try { + compileClasspathLoader.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + } + + private static Map readSkyblockerClasses() { + Map skyblockerClasses = new HashMap<>(); + ClassFile classFile = ClassFile.of(); + + forEachClass((path, _) -> { + try { + ClassModel model = classFile.parse(path); + + skyblockerClasses.put(path, model); + } catch (Exception e) { + LOGGER.error("Failed to parse class {}", path, e); + } }); + + return skyblockerClasses; } - public static void forEachClass(@NotNull File directory, BiConsumer consumer) { + /// Builds a {@code ClassHierarchyResolver} for Skyblocker's classes. + private static ClassHierarchyResolver skyblockerClassHierarchyResolver(Map classes) { + List interfaces = new ArrayList<>(); + Map classToSuperClass = new HashMap<>(); + + for (ClassModel model : classes.values()) { + ClassDesc desc = model.thisClass().asSymbol(); + + if (model.flags().has(AccessFlag.INTERFACE)) { + interfaces.add(desc); + } + + if (!model.isModuleInfo() && !desc.equals(ConstantDescs.CD_Object)) { + classToSuperClass.put(desc, model.superclass().get().asSymbol()); + } + } + + return ClassHierarchyResolver.of(interfaces, classToSuperClass); + } + + /// Builds a {@code ClassHierarchyResolver} for all classes on the compile time classpath. + private static ClassHierarchyResolver compileClasspathHierarchyResolver(JavaCompile javaCompile) { + // Creates a URLClassLoader that will provide the compile classes to the ClassFile API on-demand. + URL[] urls = javaCompile.getClasspath().getFiles().stream() + .map(File::toURI) + .map(uri -> { + try { + return uri.toURL(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }) + .toArray(URL[]::new); + compileClasspathLoader = new URLClassLoader(urls, null); + + // We only want the classes to be parsed, not completely loaded so we want the resource parsing resolver. + return ClassHierarchyResolver.ofResourceParsing(compileClasspathLoader); + } + + public static void forEachClass(File directory, BiConsumer consumer) { try { Files.walkFileTree(directory.toPath(), new SimpleFileVisitor<>() { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { if (!path.toString().endsWith(".class")) return FileVisitResult.CONTINUE; + try (InputStream inputStream = Files.newInputStream(path)) { consumer.accept(path, inputStream); } catch (IOException e) { - logger.error("Failed to run consumer on class {}", path, e); + LOGGER.error("Failed to run consumer on class {}", path, e); } return FileVisitResult.CONTINUE; } }); } catch (IOException e) { - logger.error("Failed to walk classes", e); + LOGGER.error("Failed to walk classes", e); } } @@ -73,10 +161,10 @@ public static void forEachClass(BiConsumer consumer) { } public static void forEachClass(Consumer consumer) { - forEachClass((_path, inputStream) -> consumer.accept(inputStream)); + forEachClass((_, inputStream) -> consumer.accept(inputStream)); } - public static @Nullable File findClass(File directory, String className) { + private static @Nullable File findClass(File directory, String className) { if (!className.endsWith(".class")) className += ".class"; if (!directory.isDirectory()) throw new IllegalArgumentException("Not a directory"); @@ -97,54 +185,49 @@ public static void forEachClass(Consumer consumer) { return findClass(classesDir, className); } - public static void readClass(InputStream classData, Function visitorFactory) { - try { - ClassReader classReader = new ClassReader(classData); - classReader.accept(visitorFactory.apply(classReader), ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static void writeClass(Path classFilePath, Function visitorFactory) { - try (InputStream inputStream = Files.newInputStream(classFilePath)) { - ClassReader classReader = new ClassReader(inputStream); - //ASM's frame calculation reads classes reflectively which will cause a TypeNotPresentException - //since the classes we are transforming aren't on the class path. So we need to manually calculate - //the stack frames. - ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); - classReader.accept(visitorFactory.apply(classWriter), 0); - - try (OutputStream outputStream = Files.newOutputStream(classFilePath)) { - outputStream.write(classWriter.toByteArray()); - } + public static void writeClass(Path classFilePath, byte[] classBytes) { + try (OutputStream outputStream = Files.newOutputStream(classFilePath)) { + outputStream.write(classBytes); } catch (Exception e) { throw new RuntimeException(e); } } - /** - * Pretty much [child instanceof superClass] - *

- * Classes are full name. Example: de/hysky/skyblocker/SkyblockerMod - * @param child the class to test - * @param superClass super - * @return if child is an instance of superclass - */ - public static boolean instanceOf(String child, String superClass) { + /// Pretty much [child instanceof superClass] + /// + /// @param child the class to test + /// @param superClass the super class + /// + /// @return whether the child is an instance of {@code superClass} + public static boolean instanceOf(ClassDesc child, ClassDesc superClass) { + ClassFile context = ClassFile.of(); Path start = classesDir.toPath(); - String sup = child; + ClassDesc sup = child; + while (sup != null) { if (sup.equals(superClass)) return true; - Path resolve = start.resolve(sup + ".class"); - try (InputStream stream = Files.newInputStream(resolve)) { - ClassReader classReader = new ClassReader(stream); - sup = classReader.getSuperName(); - } catch (IOException e) { - logger.error("Failed to read class {}", resolve, e); + Path resolve = start.resolve(sup.descriptorString().replace(";", "").replaceFirst("L", "") + ".class"); + + try { + ClassModel classModel = context.parse(resolve); + sup = classModel.superclass().get().asSymbol(); + } catch (Exception e) { + LOGGER.error("Failed to read class {}", resolve, e); return false; } } + return false; } + + /// Prints out any {@code VerifyErrors} that arise from class transformations. + /// + /// All class transformations should call this at the end to ensure everything is correct. + public static void verifyClass(ClassFile context, ClassDesc desc, byte[] newClassBytes) { + List verifyErrors = context.verify(newClassBytes); + + for (VerifyError error : verifyErrors) { + System.out.println("Verify error for '%s': %s".formatted(desc.packageName(), error)); + } + } } diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudInjectClassVisitor.java b/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudInjectClassVisitor.java deleted file mode 100644 index 73deb1fbdb..0000000000 --- a/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudInjectClassVisitor.java +++ /dev/null @@ -1,44 +0,0 @@ -package de.hysky.skyblocker.hud; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodNode; - -import java.util.List; - -public class HudInjectClassVisitor extends ClassVisitor { - - private final List widgetClasses; - - protected HudInjectClassVisitor(ClassVisitor delegate, List widgetClasses) { - super(Opcodes.ASM9, delegate); - this.widgetClasses = widgetClasses; - } - - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - if ((access & Opcodes.ACC_PRIVATE) != 0 && (access & Opcodes.ACC_STATIC) != 0 && name.equals("instantiateWidgets") && descriptor.equals("()V")) { - MethodNode methodNode = new MethodNode(Opcodes.ASM9, access, name, descriptor, signature, exceptions); - - for (ClassNode widget : widgetClasses) { - methodNode.visitTypeInsn(Opcodes.NEW, widget.name); - methodNode.visitInsn(Opcodes.DUP); - methodNode.visitMethodInsn(Opcodes.INVOKESPECIAL, widget.name, "", "()V", false); - methodNode.visitMethodInsn(Opcodes.INVOKESTATIC, "de/hysky/skyblocker/skyblock/tabhud/screenbuilder/WidgetManager", "addWidgetInstance", "(Lde/hysky/skyblocker/skyblock/tabhud/widget/HudWidget;)V", false); - } - - // Return from the method - methodNode.visitInsn(Opcodes.RETURN); - - // Apply our new method node to the visitor to replace the original one - methodNode.accept(this.getDelegate()); - - return null; - } - - return super.visitMethod(access, name, descriptor, signature, exceptions); - } -} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudInjector.java b/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudInjector.java new file mode 100644 index 0000000000..114c6ccb3c --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudInjector.java @@ -0,0 +1,40 @@ +package de.hysky.skyblocker.hud; + +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.CodeModel; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; +import java.lang.constant.MethodTypeDesc; +import java.util.List; + +import de.hysky.skyblocker.Processor; +import de.hysky.skyblocker.utils.MethodReference; + +public class HudInjector { + private static final ClassDesc WIDGETS_MANAGER_DESC = ClassDesc.of("de.hysky.skyblocker.skyblock.tabhud.screenbuilder.WidgetManager"); + private static final MethodReference INIT_WIDGETS_METHOD_REFERENCE = new MethodReference(WIDGETS_MANAGER_DESC, "instantiateWidgets", MethodTypeDesc.of(ConstantDescs.CD_void), false); + + public static byte[] transformClass(ClassFile context, ClassModel classModel, List widgetClasses) { + byte[] newBytes = context.transformClass(classModel, ClassTransform.transformingMethods(INIT_WIDGETS_METHOD_REFERENCE::matches, (methodBuilder, methodElement) -> { + if (methodElement instanceof CodeModel) { + methodBuilder.withCode(codeBuilder -> { + for (ClassDesc widgetClass : widgetClasses) { + codeBuilder.new_(widgetClass); + codeBuilder.dup(); + codeBuilder.invokespecial(widgetClass, "", MethodTypeDesc.of(ConstantDescs.CD_void)); + codeBuilder.invokestatic(WIDGETS_MANAGER_DESC, "addWidgetInstance", MethodTypeDesc.of(ConstantDescs.CD_void, ClassDesc.of("de.hysky.skyblocker.skyblock.tabhud.widget.HudWidget"))); + } + + codeBuilder.return_(); + }); + } else { + methodBuilder.with(methodElement); + } + })); + Processor.verifyClass(context, classModel.thisClass().asSymbol(), newBytes); + + return newBytes; + } +} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudProcessor.java b/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudProcessor.java index 8dee1c5e42..771ee68e11 100644 --- a/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudProcessor.java +++ b/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudProcessor.java @@ -1,85 +1,43 @@ package de.hysky.skyblocker.hud; -import de.hysky.skyblocker.Processor; -import org.gradle.api.tasks.compile.JavaCompile; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodNode; - -import java.io.InputStream; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.constant.ClassDesc; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; -public class HudProcessor { +import de.hysky.skyblocker.Processor; - private final Map annotatedClassesConstructors = new HashMap<>(); +public class HudProcessor { - public void apply(JavaCompile task) { + public static void apply(ClassFile context, Map classes) { long start = System.currentTimeMillis(); + Map registeredHudWidgets = new HashMap<>(); - Processor.forEachClass(this::visitClass); - - List constructors = new ArrayList<>(annotatedClassesConstructors.keySet()); - constructors.sort(Comparator.comparingInt(annotatedClassesConstructors::get)); - - inject(constructors); + // Read all classes for HudWidgets + for (Map.Entry entry : classes.entrySet()) { + HudReader.readClass(entry.getValue(), registeredHudWidgets); + } - System.out.println("Injecting widget instancing took: " + (System.currentTimeMillis() - start) + "ms"); - } + // Sort by priority + List widgetClasses = new ArrayList<>(registeredHudWidgets.keySet()); + widgetClasses.sort(Comparator.comparingInt(registeredHudWidgets::get)); - private void visitClass(InputStream inputStream) { + // Inject Hud Widget initializers try { - ClassNode classNode = new ClassNode(Opcodes.ASM9); - Processor.readClass(inputStream, classReader -> classNode); - - // Look for the annotation - boolean annotationFound = false; - int priority = 0; - List annotationNodes = new ArrayList<>(classNode.visibleAnnotations == null ? List.of() : classNode.visibleAnnotations); - annotationNodes.addAll(classNode.invisibleAnnotations == null ? List.of() : classNode.invisibleAnnotations); - for (AnnotationNode annotationNode : annotationNodes) { - String desc = annotationNode.desc; - if (!desc.equals("Lde/hysky/skyblocker/annotations/RegisterWidget;")) continue; - - annotationFound = true; - // null if no parameters are given, defaults don't show up :shrug: - if (annotationNode.values != null) { - for (int i = 0; i < annotationNode.values.size(); i++) { - if ("priority".equals(annotationNode.values.get(i))) { - priority = (int) annotationNode.values.get(i + 1); - } - } - } - break; - } - if (!annotationFound) return; - if (!Processor.instanceOf(classNode.name, "de/hysky/skyblocker/skyblock/tabhud/widget/HudWidget")) { - throw new IllegalArgumentException("Class " + classNode.name + " has @RegisterWidget annotation but does not extend HudWidget"); - } - - // Look for constructor - MethodNode constructor = null; - for (MethodNode method : classNode.methods) { - if (!method.name.equals("")) continue; - if (!method.desc.equals("()V")) continue; - constructor = method; - break; - } - if (constructor == null) throw new IllegalStateException("No parameterless constructor found for " + classNode.name); - - annotatedClassesConstructors.put(classNode, priority); - - + Path widgetsManagerClassFile = Objects.requireNonNull(Processor.findClass("WidgetManager.class"), "WidgetManager class wasn't found :(").toPath(); + byte[] classBytes = HudInjector.transformClass(context, context.parse(widgetsManagerClassFile), widgetClasses); + Processor.writeClass(widgetsManagerClassFile, classBytes); } catch (Exception e) { throw new RuntimeException(e); } - } - private void inject(List constructors) { - Path mainClassFile = Objects.requireNonNull(Processor.findClass("WidgetManager.class"), "WidgetManager class wasn't found :(").toPath(); - - Processor.writeClass(mainClassFile, classWriter -> new HudInjectClassVisitor(classWriter, constructors)); + System.out.println("Injecting widget instancing took: " + (System.currentTimeMillis() - start) + "ms"); } } diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudReader.java b/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudReader.java new file mode 100644 index 0000000000..7fb9c03264 --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/hud/HudReader.java @@ -0,0 +1,67 @@ +package de.hysky.skyblocker.hud; + +import java.lang.classfile.Annotation; +import java.lang.classfile.AnnotationElement; +import java.lang.classfile.AnnotationValue; +import java.lang.classfile.Attributes; +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; +import java.lang.classfile.attribute.RuntimeInvisibleAnnotationsAttribute; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; +import java.lang.constant.MethodTypeDesc; +import java.lang.reflect.AccessFlag; +import java.util.Map; +import java.util.Optional; + +import de.hysky.skyblocker.Processor; + +public class HudReader { + private static final ClassDesc REGISTER_WIDGET_ANNOTATION_DESC = ClassDesc.of("de.hysky.skyblocker.annotations.RegisterWidget"); + private static final ClassDesc HUD_WIDGET_DESC = ClassDesc.of("de.hysky.skyblocker.skyblock.tabhud.widget.HudWidget"); + private static final MethodTypeDesc DEFAULT_CONSTRUCTOR_DESC = MethodTypeDesc.of(ConstantDescs.CD_void); + + public static void readClass(ClassModel classModel, Map registeredHudWidgets) { + Optional runtimeInvisibleAnnotationsOpt = classModel.findAttribute(Attributes.runtimeInvisibleAnnotations()); + + if (runtimeInvisibleAnnotationsOpt.isPresent()) { + RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotations = runtimeInvisibleAnnotationsOpt.get(); + + for (Annotation annotation : runtimeInvisibleAnnotations.annotations()) { + if (annotation.classSymbol().equals(REGISTER_WIDGET_ANNOTATION_DESC)) { + checkSuperClass(classModel); + checkForDefaultConstructor(classModel); + + AnnotationValue priorityValue = annotation.elements().stream() + .filter(annotationElement -> annotationElement.name().equalsString("priority")) + .map(AnnotationElement::value) + .findAny() + .orElse(null); + int priority = priorityValue instanceof AnnotationValue.OfInt intValue ? intValue.intValue() : 0; + + registeredHudWidgets.put(classModel.thisClass().asSymbol(), priority); + } + } + } + } + + /// Requires that widgets extend {@code HudWidget}. + private static void checkSuperClass(ClassModel classModel) { + if (classModel.superclass().isPresent() && Processor.instanceOf(classModel.thisClass().asSymbol(), HUD_WIDGET_DESC)) { + return; + } + + throw new IllegalStateException("Class " + classModel.thisClass().asSymbol().packageName() + "is annotated with @RegisterWidget but does not extend HudWidget!"); + } + + /// Requires that widgets have a no-args constructor that is public. + private static void checkForDefaultConstructor(ClassModel classModel) { + for (MethodModel methodModel : classModel.methods()) { + if (methodModel.flags().has(AccessFlag.PUBLIC) && methodModel.methodName().equalsString("") && methodModel.methodTypeSymbol().equals(DEFAULT_CONSTRUCTOR_DESC)) { + return; + } + } + + throw new IllegalStateException("Did not find a public, no-args constructor found for " + classModel.thisClass().asSymbol().displayName() + "!"); + } +} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/hud/package-info.java b/buildSrc/src/main/java/de/hysky/skyblocker/hud/package-info.java new file mode 100644 index 0000000000..ba7ec714c3 --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/hud/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package de.hysky.skyblocker.hud; + +import org.jspecify.annotations.NullMarked; diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/init/InitInjectingClassVisitor.java b/buildSrc/src/main/java/de/hysky/skyblocker/init/InitInjectingClassVisitor.java deleted file mode 100644 index a041f056a8..0000000000 --- a/buildSrc/src/main/java/de/hysky/skyblocker/init/InitInjectingClassVisitor.java +++ /dev/null @@ -1,43 +0,0 @@ -package de.hysky.skyblocker.init; - -import de.hysky.skyblocker.MethodReference; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.MethodNode; - -import java.util.List; - -public class InitInjectingClassVisitor extends ClassVisitor { - private final List methodSignatures; - - public InitInjectingClassVisitor(ClassVisitor classVisitor, List methodSignatures) { - super(Opcodes.ASM9, classVisitor); - this.methodSignatures = methodSignatures; - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - // Limit replacing to the init method which is private, static, named init, has no args, and has a void return type - if ((access & Opcodes.ACC_PRIVATE) != 0 && (access & Opcodes.ACC_STATIC) != 0 && name.equals("init") && descriptor.equals("()V")) { - // Method node that we will overwrite the init method with - MethodNode methodNode = new MethodNode(Opcodes.ASM9, access, name, descriptor, signature, exceptions); - - // Inject calls to each found @Init annotated method - for (MethodReference methodCall : methodSignatures) { - methodNode.visitMethodInsn(Opcodes.INVOKESTATIC, methodCall.className(), methodCall.methodName(), methodCall.descriptor(), methodCall.itf()); - } - - // Return from the method - methodNode.visitInsn(Opcodes.RETURN); - - // Apply our new method node to the visitor to replace the original one - methodNode.accept(this.getDelegate()); - - return null; - } - - return super.visitMethod(access, name, descriptor, signature, exceptions); - } -} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/init/InitInjector.java b/buildSrc/src/main/java/de/hysky/skyblocker/init/InitInjector.java new file mode 100644 index 0000000000..37ad9ef43c --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/init/InitInjector.java @@ -0,0 +1,36 @@ +package de.hysky.skyblocker.init; + +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.CodeModel; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; +import java.lang.constant.MethodTypeDesc; +import java.util.List; + +import de.hysky.skyblocker.Processor; +import de.hysky.skyblocker.utils.MethodReference; + +public class InitInjector { + private static final MethodReference INIT_METHOD_REFERENCE = new MethodReference(ClassDesc.of("de.hysky.skyblocker.SkyblockerMod"), "init", MethodTypeDesc.of(ConstantDescs.CD_void), false); + + public static byte[] transformClass(ClassFile context, ClassModel classModel, List initMethodReferences) { + byte[] newBytes = context.transformClass(classModel, ClassTransform.transformingMethods(INIT_METHOD_REFERENCE::matches, (methodBuilder, methodElement) -> { + if (methodElement instanceof CodeModel) { + methodBuilder.withCode(codeBuilder -> { + for (MethodReference methodReference : initMethodReferences) { + codeBuilder.invokestatic(methodReference.classDesc(), methodReference.methodName(), methodReference.typeDesc(), methodReference.itf()); + } + + codeBuilder.return_(); + }); + } else { + methodBuilder.with(methodElement); + } + })); + Processor.verifyClass(context, classModel.thisClass().asSymbol(), newBytes); + + return newBytes; + } +} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/init/InitProcessor.java b/buildSrc/src/main/java/de/hysky/skyblocker/init/InitProcessor.java index 2b398bb965..09538ac79b 100644 --- a/buildSrc/src/main/java/de/hysky/skyblocker/init/InitProcessor.java +++ b/buildSrc/src/main/java/de/hysky/skyblocker/init/InitProcessor.java @@ -1,44 +1,43 @@ package de.hysky.skyblocker.init; -import de.hysky.skyblocker.MethodReference; -import de.hysky.skyblocker.Processor; -import org.gradle.api.tasks.compile.JavaCompile; - +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; import java.nio.file.Path; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -@SuppressWarnings("unused") +import de.hysky.skyblocker.Processor; +import de.hysky.skyblocker.utils.MethodReference; + public class InitProcessor { - public void apply(JavaCompile task) { + public static void apply(ClassFile context, Map classes) { long start = System.currentTimeMillis(); Map methodSignatures = new HashMap<>(); - //Find all methods with the @Init annotation - findInitMethods(methodSignatures); + // Find all methods with the @Init annotation + for (Map.Entry entry : classes.entrySet()) { + InitReader.readClass(entry.getValue(), methodSignatures); + } - //Sort the methods by their priority. It's also converted to a list because the priority values are useless from here on + // Sort the methods by their priority. Its also converted to a list because the priority values are useless from here on List sortedMethodSignatures = methodSignatures.entrySet() .stream() - .sorted(Map.Entry.comparingByValue().thenComparing(entry -> entry.getKey().className())) + .sorted(Map.Entry.comparingByValue().thenComparing(entry -> entry.getKey().classDesc().packageName())) .map(Map.Entry::getKey) .toList(); - //Inject calls to the @Init annotated methods in the SkyblockerMod class - injectInitCalls(sortedMethodSignatures); - - System.out.println("Injecting init methods took: " + (System.currentTimeMillis() - start) + "ms"); - } + // Inject calls to the @Init annotated methods in the SkyblockerMod class + try { + Path mainClassFile = Objects.requireNonNull(Processor.findClass("SkyblockerMod.class"), "SkyblockerMod class wasn't found :(").toPath(); + byte[] classBytes = InitInjector.transformClass(context, context.parse(mainClassFile), sortedMethodSignatures); - public void findInitMethods(Map methodSignatures) { - Processor.forEachClass(inputStream -> Processor.readClass(inputStream, classReader -> new InitReadingClassVisitor(classReader, methodSignatures))); - } + Processor.writeClass(mainClassFile, classBytes); + } catch (Exception e) { + throw new RuntimeException(e); + } - public void injectInitCalls(List methodSignatures) { - Path mainClassFile = Objects.requireNonNull(Processor.findClass("SkyblockerMod.class"), "SkyblockerMod class wasn't found :(").toPath(); - - Processor.writeClass(mainClassFile, classWriter -> new InitInjectingClassVisitor(classWriter, methodSignatures)); + System.out.println("Injecting init methods took: " + (System.currentTimeMillis() - start) + "ms"); } } diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/init/InitReader.java b/buildSrc/src/main/java/de/hysky/skyblocker/init/InitReader.java new file mode 100644 index 0000000000..0b1091169d --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/init/InitReader.java @@ -0,0 +1,64 @@ +package de.hysky.skyblocker.init; + +import java.lang.classfile.Annotation; +import java.lang.classfile.AnnotationElement; +import java.lang.classfile.AnnotationValue; +import java.lang.classfile.Attributes; +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; +import java.lang.classfile.attribute.RuntimeInvisibleAnnotationsAttribute; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; +import java.lang.constant.MethodTypeDesc; +import java.lang.reflect.AccessFlag; +import java.util.Map; +import java.util.Optional; + +import de.hysky.skyblocker.utils.MethodReference; + +public class InitReader { + private static final ClassDesc INIT_ANNOTATION_DESC = ClassDesc.of("de.hysky.skyblocker.annotations.Init"); + + public static void readClass(ClassModel classModel, Map initMethodReferences) { + for (MethodModel methodModel : classModel.methods()) { + Optional runtimeInvisibleAnnotationsOpt = methodModel.findAttribute(Attributes.runtimeInvisibleAnnotations()); + + if (runtimeInvisibleAnnotationsOpt.isPresent()) { + RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotations = runtimeInvisibleAnnotationsOpt.get(); + + for (Annotation annotation : runtimeInvisibleAnnotations.annotations()) { + if (annotation.classSymbol().equals(INIT_ANNOTATION_DESC)) { + // Ensure that this is a valid init method + checkInitMethod(methodModel); + + AnnotationValue priorityValue = annotation.elements().stream() + .filter(annotationElement -> annotationElement.name().equalsString("priority")) + .map(AnnotationElement::value) + .findAny() + .orElse(null); + int priority = priorityValue instanceof AnnotationValue.OfInt intValue ? intValue.intValue() : 0; + MethodReference methodReference = MethodReference.fromModel(methodModel); + + initMethodReferences.put(methodReference, priority); + } + } + } + } + } + + /// Requires that init methods are public, static, have no parameters, and have a void return type. + private static void checkInitMethod(MethodModel methodModel) { + if (!methodModel.flags().has(AccessFlag.PUBLIC)) { + throw new IllegalStateException(methodModel.toDebugString() + ": Initializer methods must be public"); + } + + if (!methodModel.flags().has(AccessFlag.STATIC)) { + throw new IllegalStateException(methodModel.toDebugString() + ": Initializer methods must be static"); + } + + MethodTypeDesc typeDesc = methodModel.methodTypeSymbol(); + if (typeDesc.parameterCount() > 0 || !typeDesc.returnType().equals(ConstantDescs.CD_void)) { + throw new IllegalStateException(methodModel.toDebugString() + ": Initializer methods must have no arguments and a void return type"); + } + } +} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/init/InitReadingClassVisitor.java b/buildSrc/src/main/java/de/hysky/skyblocker/init/InitReadingClassVisitor.java deleted file mode 100644 index a892a6c818..0000000000 --- a/buildSrc/src/main/java/de/hysky/skyblocker/init/InitReadingClassVisitor.java +++ /dev/null @@ -1,73 +0,0 @@ -package de.hysky.skyblocker.init; - -import org.jetbrains.annotations.NotNull; -import org.objectweb.asm.*; - -import java.util.Map; - -import de.hysky.skyblocker.MethodReference; - -public class InitReadingClassVisitor extends ClassVisitor { - private final Map methodSignatures; - private final ClassReader classReader; - - public InitReadingClassVisitor(ClassReader classReader, Map methodSignatures) { - super(Opcodes.ASM9); - this.classReader = classReader; - this.methodSignatures = methodSignatures; - } - - @Override - public MethodVisitor visitMethod(int access, String methodName, String descriptor, String signature, String[] exceptions) { - return new MethodVisitor(Opcodes.ASM9) { - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - //This method visitor checks all methods and only acts upon those with the Init annotation. - //This lets us warn the user about invalid init methods and misuse of the annotation - if (!desc.equals("Lde/hysky/skyblocker/annotations/Init;")) return super.visitAnnotation(desc, visible); - - //Delegates adding the method call to the map to the InitAnnotationVisitor since we don't have a value to put in the map here - return new InitAnnotationVisitor(methodSignatures, getMethodCall()); - } - - private @NotNull MethodReference getMethodCall() { - String className = classReader.getClassName(); - String methodCallString = className + "." + methodName; - if ((access & Opcodes.ACC_PUBLIC) == 0) throw new IllegalStateException(methodCallString + ": Initializer methods must be public"); - if ((access & Opcodes.ACC_STATIC) == 0) throw new IllegalStateException(methodCallString + ": Initializer methods must be static"); - if (!descriptor.equals("()V")) throw new IllegalStateException(methodCallString + ": Initializer methods must have no args and a void return type"); - - //Interface static methods need special handling, so we add a special marker for that - boolean itf = (classReader.getAccess() & Opcodes.ACC_INTERFACE) != 0; - - return new MethodReference(className, methodName, descriptor, itf); - } - }; - } - - static class InitAnnotationVisitor extends AnnotationVisitor { - private final Map methodSignatures; - private final MethodReference methodCall; - - protected InitAnnotationVisitor(Map methodSignatures, MethodReference methodCall) { - super(Opcodes.ASM9); - this.methodSignatures = methodSignatures; - this.methodCall = methodCall; - } - - @Override - public void visitEnd() { - //Annotations that use the default value for the priority field will not be called by the visit method, so we have to handle them here. - methodSignatures.putIfAbsent(methodCall, 0); - super.visitEnd(); - } - - @Override - public void visit(String name, Object value) { - if (name.equals("priority")) { - methodSignatures.put(methodCall, (int) value); - } - super.visit(name, value); - } - } -} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/init/package-info.java b/buildSrc/src/main/java/de/hysky/skyblocker/init/package-info.java new file mode 100644 index 0000000000..c43252f18d --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/init/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package de.hysky.skyblocker.init; + +import org.jspecify.annotations.NullMarked; diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectInjectingClassVisitor.java b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectInjectingClassVisitor.java deleted file mode 100644 index 300bfae4e1..0000000000 --- a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectInjectingClassVisitor.java +++ /dev/null @@ -1,169 +0,0 @@ -package de.hysky.skyblocker.object; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.invoke.TypeDescriptor; -import java.util.List; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.MethodNode; - -import de.hysky.skyblocker.FieldReference; - -public class ObjectInjectingClassVisitor extends ClassVisitor { - /** - * The descriptor of the {@link java.lang.runtime.ObjectMethods#bootstrap} method. - */ - private static final String BOOTSTRAP_DESCRIPTOR = MethodType.methodType( - Object.class, - MethodHandles.Lookup.class, - String.class, - TypeDescriptor.class, - Class.class, - String.class, - MethodHandle[].class - ).toMethodDescriptorString(); - private final List objectMethodsToGenerate; - - public ObjectInjectingClassVisitor(ClassVisitor classVisitor, List objectMethodsToGenerate) { - super(Opcodes.ASM9, classVisitor); - this.objectMethodsToGenerate = objectMethodsToGenerate; - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - ObjectMethodGeneration objectMethod = this.objectMethodsToGenerate.stream() - .filter(om -> om.target().matches(name, descriptor)) - .findAny() - .orElse(null); - - //If we aren't meant to inject into this method then return - if (objectMethod == null) { - return super.visitMethod(access, name, descriptor, signature, exceptions); - } - - //Remove native modifier - access &= ~Opcodes.ACC_NATIVE; - MethodNode methodNode = new MethodNode(Opcodes.ASM9, access, name, descriptor, signature, exceptions); - - //Load the "this" variable since the resulting method handle takes it in as a parameter - methodNode.visitVarInsn(Opcodes.ALOAD, 0); - - //Load the other object parameter from equals method (2nd local variable) if applicable - if (objectMethod.objectMethodType() == ObjectMethodType.EQUALS) { - methodNode.visitVarInsn(Opcodes.ALOAD, 1); - } - - //Emit the INDY instruction - emitIndyInstruction(objectMethod, methodNode); - - //Emit instructions to consider superclass equals and hash codes when applicable - //Note that the result from the INDY is on the stack already! - if (objectMethod.superClassReference() != null) { - //These methods also emit the necessary return instructions - switch (objectMethod.objectMethodType()) { - case ObjectMethodType.EQUALS -> emitEqualsSuperInstructions(objectMethod, methodNode); - case ObjectMethodType.HASH_CODE -> emitHashCodeSuperInstructions(objectMethod, methodNode); - case ObjectMethodType.TO_STRING -> throw new UnsupportedOperationException("Cannot compute toString values for superclasses!"); - } - } else { - //Emit return instruction if we only care about the current class - methodNode.visitInsn(switch (objectMethod.objectMethodType()) { - case ObjectMethodType.EQUALS, ObjectMethodType.HASH_CODE -> Opcodes.IRETURN; - case ObjectMethodType.TO_STRING -> Opcodes.ARETURN; - }); - } - - //Replace the target method with our new generated one - methodNode.accept(this.getDelegate()); - - return null; - } - - private void emitIndyInstruction(ObjectMethodGeneration objectMethod, MethodNode methodNode) { - //This is the name of our Call Site which ObjectMethods#bootstrap infers as the name of the method to generate - String callSiteName = switch (objectMethod.objectMethodType()) { - case ObjectMethodType.EQUALS -> "equals"; - case ObjectMethodType.HASH_CODE -> "hashCode"; - case ObjectMethodType.TO_STRING -> "toString"; - }; - - //The descriptor of the Call Site - the first parameter is the current class/instance (since the MH the INDY produces needs the instance - //to operate on), followed by the method's parameters (optional), and then the return type. - String callSiteDescriptor = "(" + objectMethod.classReference().descriptor() + switch (objectMethod.objectMethodType()) { - case ObjectMethodType.EQUALS -> "Ljava/lang/Object;)Z"; - case ObjectMethodType.HASH_CODE -> ")I"; - case ObjectMethodType.TO_STRING -> ")Ljava/lang/String;"; - }; - //The handle that links to ObjectMethods#bootstrap - Handle bootstrapHandle = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/runtime/ObjectMethods", "bootstrap", BOOTSTRAP_DESCRIPTOR, false); - - //INDY bootstrap arguments - - //The type of the current class - Type type = Type.getType(objectMethod.classReference().descriptor()); - //Concat of all the field names separated by ';' as required by ObjectMethods#bootstrap - String fieldNamesConcat = String.join(";", objectMethod.fieldReferences().stream() - .map(FieldReference::fieldName) - .toArray(String[]::new)); - //Handles to each field involved in the operation - Handle[] fieldHandles = objectMethod.fieldReferences().stream() - .map(ref -> new Handle(Opcodes.H_GETFIELD, ref.className(), ref.fieldName(), ref.descriptor(), false)) - .toArray(Handle[]::new); - - //Compile arguments into array - //type + name concat + field handles (must be in this order!) - Object bsmArgs[] = new Object[2 + fieldHandles.length]; - bsmArgs[0] = type; - bsmArgs[1] = fieldNamesConcat; - System.arraycopy(fieldHandles, 0, bsmArgs, 2, fieldHandles.length); - - methodNode.visitInvokeDynamicInsn(callSiteName, callSiteDescriptor, bootstrapHandle, bsmArgs); - } - - /** - * Effectively performs a Logical AND with the result of the generated equals and the superclass' equals method. - * - * Looks like: {@code return instanceEquals(o) ? superEquals(o) : false} in Java code. - */ - private void emitEqualsSuperInstructions(ObjectMethodGeneration objectMethod, MethodNode methodNode) { - //Label representing the branch for instanceEquals(o) returning false - //Note that IFEQ succeeds only if the preceding value on the stack (instanceEquals(o) result) was 0 (false) - //so we will either continue onto the next instructions (if true) or jump to the false branch. - Label notEquals = new Label(); - methodNode.visitJumpInsn(Opcodes.IFEQ, notEquals); - - methodNode.visitVarInsn(Opcodes.ALOAD, 0); - methodNode.visitVarInsn(Opcodes.ALOAD, 1); - methodNode.visitMethodInsn(Opcodes.INVOKESPECIAL, objectMethod.superClassReference().className(), "equals", "(Ljava/lang/Object;)Z", false); - methodNode.visitInsn(Opcodes.IRETURN); - - //False branch - //Return false since instanceEquals(o) was false - methodNode.visitLabel(notEquals); - methodNode.visitFrame(Opcodes.F_SAME, 0, null, 0, null); - methodNode.visitInsn(Opcodes.ICONST_0); //0 = false - methodNode.visitInsn(Opcodes.IRETURN); - } - - /** - * Combines the hash code produced by the INDY and the one from the superclass. - * - * Looks like: {@code instanceHash() * 31 + superHash()} in Java code. - */ - private void emitHashCodeSuperInstructions(ObjectMethodGeneration objectMethod, MethodNode methodNode) { - //Load 31 onto the stack & multiply it with the instanceHash, then get superHash and add it to the result. - methodNode.visitIntInsn(Opcodes.BIPUSH, 31); - methodNode.visitInsn(Opcodes.IMUL); - methodNode.visitVarInsn(Opcodes.ALOAD, 0); - methodNode.visitMethodInsn(Opcodes.INVOKESPECIAL, objectMethod.superClassReference().className(), "hashCode", "()I", false); - methodNode.visitInsn(Opcodes.IADD); - methodNode.visitInsn(Opcodes.IRETURN); - } -} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodAnnotationVisitor.java b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodAnnotationVisitor.java deleted file mode 100644 index 8f9659a3c7..0000000000 --- a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodAnnotationVisitor.java +++ /dev/null @@ -1,25 +0,0 @@ -package de.hysky.skyblocker.object; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Opcodes; - -public class ObjectMethodAnnotationVisitor extends AnnotationVisitor { - private boolean includeSuper = false; - - public ObjectMethodAnnotationVisitor() { - super(Opcodes.ASM9); - } - - @Override - public void visit(String name, Object value) { - if (name.equals("includeSuper")) { - this.includeSuper = (boolean) value; - } - - super.visit(name, value); - } - - public boolean getIncludeSuper() { - return this.includeSuper; - } -} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodGeneration.java b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodGeneration.java index 2208cb7783..f0e44de0eb 100644 --- a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodGeneration.java +++ b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodGeneration.java @@ -1,21 +1,18 @@ package de.hysky.skyblocker.object; +import java.lang.constant.ClassDesc; import java.util.List; +import java.util.Optional; -import org.jetbrains.annotations.Nullable; +import de.hysky.skyblocker.utils.FieldReference; +import de.hysky.skyblocker.utils.MethodReference; -import de.hysky.skyblocker.ClassReference; -import de.hysky.skyblocker.FieldReference; -import de.hysky.skyblocker.MethodReference; - -/** - * Record representing information about an {@link Object} method to generate in a class. - * - * @param objectMethodType The type method that we are generating. - * @param target The target method to replace in the class. - * @param classReference The reference to the class that the method will be generated in. - * @param fieldReferences The fields to incorporate in the generated method (e.g. what fields will be used for equals, hashCode, and toString). - * @param superClassReference The reference to the class' superclass. Only applicable to equals and hashCode, and is only non-null if the super class should be considered by the operation. - */ -public record ObjectMethodGeneration(MethodReference target, ObjectMethodType objectMethodType, ClassReference classReference, List fieldReferences, @Nullable ClassReference superClassReference) { +/// Record representing information about an {@link Object} method to generate in a class. +/// +/// @param classReference The descriptor of the class that the method will be generated in. +/// @param target The target method to replace in the class. +/// @param objectMethodType The type method that we are generating. +/// @param fieldReferences The fields to incorporate in the generated method (e.g. what fields will be used for equals, hashCode, and toString). +/// @param superClassDesc The descriptor of the class' superclass. Only applicable to equals and hashCode, and is only present if the super class should be considered by the operation. +public record ObjectMethodGeneration(ClassDesc classDesc, MethodReference target, ObjectMethodType objectMethodType, List fieldReferences, Optional superClassDesc) { } diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodInjector.java b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodInjector.java new file mode 100644 index 0000000000..fbcc1d4f2b --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodInjector.java @@ -0,0 +1,175 @@ +package de.hysky.skyblocker.object; + +import java.lang.classfile.AccessFlags; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.CodeModel; +import java.lang.classfile.MethodModel; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDesc; +import java.lang.constant.ConstantDescs; +import java.lang.constant.DirectMethodHandleDesc; +import java.lang.constant.DynamicCallSiteDesc; +import java.lang.constant.MethodHandleDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.reflect.AccessFlag; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import de.hysky.skyblocker.Processor; +import de.hysky.skyblocker.utils.FieldReference; + +public class ObjectMethodInjector { + + public static byte[] transformClass(ClassFile context, ClassModel classModel, List objectMethodsToGenerate) { + Predicate methodsToTransform = methodModel -> objectMethodsToGenerate.stream() + .map(ObjectMethodGeneration::target) + .anyMatch(methodReference -> methodReference.matches(methodModel)); + + byte[] newBytes = context.transformClass(classModel, (classBuilder, classElement) -> { + if (classElement instanceof MethodModel methodModel && methodsToTransform.test(methodModel)) { + // Find what method we are meant to generate + ObjectMethodGeneration objectMethodToGenerate = objectMethodsToGenerate.stream() + .filter(generation -> generation.target().matches(methodModel)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Could not find generation for: " + methodModel.toDebugString())); + + // Transform the method + classBuilder.transformMethod(methodModel, (methodBuilder, methodElement) -> { + switch (methodElement) { + case AccessFlags accessFlags -> { + // Remove the native flag if present + if (accessFlags.has(AccessFlag.NATIVE)) { + // Copy the access flags set + Set newAccessFlags = new HashSet<>(accessFlags.flags()); + newAccessFlags.remove(AccessFlag.NATIVE); + methodBuilder.withFlags(newAccessFlags.toArray(AccessFlag[]::new)); + + // If the method was declared native, it won't have a code attribute so we now need to add one + // since our block below that looks for a CodeModel will not run + methodBuilder.withCode(codeBuilder -> { + loadLocalVariables(objectMethodToGenerate, codeBuilder); + buildInvokeDynamic(objectMethodToGenerate, codeBuilder); + addSuperClassComparisons(objectMethodToGenerate, codeBuilder); + }); + } + } + + // This will only run if the object method was not declared as native + case CodeModel _ -> { + methodBuilder.withCode(codeBuilder -> { + loadLocalVariables(objectMethodToGenerate, codeBuilder); + buildInvokeDynamic(objectMethodToGenerate, codeBuilder); + addSuperClassComparisons(objectMethodToGenerate, codeBuilder); + }); + } + + default -> { + methodBuilder.with(methodElement); + } + } + }); + } else { + classBuilder.with(classElement); + } + }); + Processor.verifyClass(context, classModel.thisClass().asSymbol(), newBytes); + + return newBytes; + } + + private static void loadLocalVariables(ObjectMethodGeneration objectMethodToGenerate, CodeBuilder codeBuilder) { + // Load the "this" variable since the resulting method handle takes it in as a parameter + codeBuilder.aload(0); + + // Load the other object parameter from equals method (2nd local variable) + if (objectMethodToGenerate.objectMethodType() == ObjectMethodType.EQUALS) { + codeBuilder.aload(1); + } + } + + private static void buildInvokeDynamic(ObjectMethodGeneration objectMethodToGenerate, CodeBuilder codeBuilder) { + List bootstrapArgsBuilder = new ArrayList<>(); + // Add the target class + bootstrapArgsBuilder.add(objectMethodToGenerate.classDesc()); + // Add all the field names - they must be separated by a semicolon + bootstrapArgsBuilder.add(objectMethodToGenerate.fieldReferences().stream() + .map(FieldReference::fieldName) + .collect(Collectors.joining(";"))); + // Add the getter handles to all the fields + bootstrapArgsBuilder.addAll(objectMethodToGenerate.fieldReferences().stream() + .map(fieldReference -> MethodHandleDesc.of( + DirectMethodHandleDesc.Kind.GETTER, + objectMethodToGenerate.classDesc(), + fieldReference.fieldName(), + fieldReference.typeDesc().descriptorString())) + .toList()); + + DirectMethodHandleDesc bootstrapMethod = MethodHandleDesc.of( + DirectMethodHandleDesc.Kind.STATIC, + ClassDesc.of("java.lang.runtime.ObjectMethods"), + "bootstrap", + MethodTypeDesc.of( + ConstantDescs.CD_Object, + ConstantDescs.CD_MethodHandles_Lookup, + ConstantDescs.CD_String, + ClassDesc.of("java.lang.invoke.TypeDescriptor"), + ConstantDescs.CD_Class, + ConstantDescs.CD_String, + ConstantDescs.CD_MethodHandle.arrayType()).descriptorString()); + // We must also pass the current class (the one we are injecting into) as the first parameter of the invocation type since that is + // the instance that the resulting MethodHandle will need to consume, then followed by the respective parameters of the object method we are generating + MethodTypeDesc invocationType = switch (objectMethodToGenerate.objectMethodType()) { + case ObjectMethodType.EQUALS -> MethodTypeDesc.of(ConstantDescs.CD_boolean, objectMethodToGenerate.classDesc(), ConstantDescs.CD_Object); + case ObjectMethodType.HASH_CODE -> MethodTypeDesc.of(ConstantDescs.CD_int, objectMethodToGenerate.classDesc()); + case ObjectMethodType.TO_STRING -> MethodTypeDesc.of(ConstantDescs.CD_String, objectMethodToGenerate.classDesc()); + }; + ConstantDesc[] bootstrapArgs = bootstrapArgsBuilder.toArray(ConstantDesc[]::new); + DynamicCallSiteDesc callSite = DynamicCallSiteDesc.of(bootstrapMethod, objectMethodToGenerate.objectMethodType().methodName, invocationType, bootstrapArgs); + + codeBuilder.invokedynamic(callSite); + } + + private static void addSuperClassComparisons(ObjectMethodGeneration objectMethodToGenerate, CodeBuilder codeBuilder) { + if (objectMethodToGenerate.superClassDesc().isPresent()) { + switch (objectMethodToGenerate.objectMethodType()) { + case ObjectMethodType.EQUALS -> { + // The preceding boolean value on the stack is the result of the equals method on this instance: + // If the current instance is equal to the other instance then do the super class equals and return that + // Or, if the current instance and the other instance are not equal then simply return false + codeBuilder.ifThenElse(trueCodeBuilder -> { + trueCodeBuilder.aload(0); + trueCodeBuilder.aload(1); + trueCodeBuilder.invokespecial(objectMethodToGenerate.superClassDesc().get(), "equals", MethodTypeDesc.of(ConstantDescs.CD_boolean, ConstantDescs.CD_Object), false); + trueCodeBuilder.ireturn(); + }, falseCodeBuilder -> { + falseCodeBuilder.iconst_0(); + falseCodeBuilder.ireturn(); + }); + } + + case ObjectMethodType.HASH_CODE -> { + // Load 31 onto the stack and multiply it with the instance's, then get the super class' hash and add it to the result. + codeBuilder.bipush(31); + codeBuilder.imul(); + codeBuilder.aload(0); + codeBuilder.invokespecial(objectMethodToGenerate.superClassDesc().get(), "hashCode", MethodTypeDesc.of(ConstantDescs.CD_int), false); + codeBuilder.iadd(); + codeBuilder.ireturn(); + } + + case ObjectMethodType.TO_STRING -> throw new UnsupportedOperationException("Cannot compute toString values for superclasses!"); + } + } else { + switch (objectMethodToGenerate.objectMethodType()) { + case ObjectMethodType.EQUALS, ObjectMethodType.HASH_CODE -> codeBuilder.ireturn(); + case ObjectMethodType.TO_STRING -> codeBuilder.areturn(); + } + } + } +} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodReader.java b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodReader.java new file mode 100644 index 0000000000..51033d82ce --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectMethodReader.java @@ -0,0 +1,102 @@ +package de.hysky.skyblocker.object; + +import java.lang.classfile.Annotation; +import java.lang.classfile.AnnotationElement; +import java.lang.classfile.AnnotationValue; +import java.lang.classfile.Attributes; +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; +import java.lang.classfile.attribute.RuntimeInvisibleAnnotationsAttribute; +import java.lang.classfile.constantpool.ClassEntry; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; +import java.lang.constant.MethodTypeDesc; +import java.lang.reflect.AccessFlag; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Consumer; + +import de.hysky.skyblocker.utils.FieldReference; +import de.hysky.skyblocker.utils.MethodReference; +import de.hysky.skyblocker.utils.Pair; + +public class ObjectMethodReader { + private static final ClassDesc EQUALS_ANNOTATION_DESC = ClassDesc.of("de.hysky.skyblocker.annotations.GenEquals"); + private static final ClassDesc HASH_CODE_ANNOTATION_DESC = ClassDesc.of("de.hysky.skyblocker.annotations.GenHashCode"); + private static final ClassDesc TO_STRING_ANNOTATION_DESC = ClassDesc.of("de.hysky.skyblocker.annotations.GenToString"); + private static final MethodTypeDesc EQUALS_METHOD_DESC = MethodTypeDesc.of(ConstantDescs.CD_boolean, ConstantDescs.CD_Object); + private static final MethodTypeDesc HASH_CODE_METHOD_DESC = MethodTypeDesc.of(ConstantDescs.CD_int); + private static final MethodTypeDesc TO_STRING_METHOD_DESC = MethodTypeDesc.of(ConstantDescs.CD_String); + + public static void readClass(ClassModel classModel, Consumer> mapAdder) { + Map> targetMethods = new HashMap<>(); + + for (MethodModel methodModel : classModel.methods()) { + Optional runtimeInvisibleAnnotationsOpt = methodModel.findAttribute(Attributes.runtimeInvisibleAnnotations()); + + if (runtimeInvisibleAnnotationsOpt.isPresent()) { + RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotations = runtimeInvisibleAnnotationsOpt.get(); + + for (Annotation annotation : runtimeInvisibleAnnotations.annotations()) { + ClassDesc annotationDesc = annotation.classSymbol(); + + ObjectMethodType objectMethodType = switch (annotationDesc) { + case ClassDesc _ when annotationDesc.equals(EQUALS_ANNOTATION_DESC) -> ObjectMethodType.EQUALS; + case ClassDesc _ when annotationDesc.equals(HASH_CODE_ANNOTATION_DESC) -> ObjectMethodType.HASH_CODE; + case ClassDesc _ when annotationDesc.equals(TO_STRING_ANNOTATION_DESC) -> ObjectMethodType.TO_STRING; + default -> null; + }; + + if (objectMethodType != null) { + checkMethodDesc(methodModel, objectMethodType); + + if (methodModel.flags().has(AccessFlag.ABSTRACT)) { + throw new IllegalStateException("Methods that generate an Object method must not be abstract! Use the native modifier if you do not want a stub method body."); + } + + AnnotationValue includeSuperValue = annotation.elements().stream() + .filter(annotationElement -> annotationElement.name().equalsString("includeSuper")) + .map(AnnotationElement::value) + .findAny() + .orElse(null); + boolean includeSuper = includeSuperValue instanceof AnnotationValue.OfBoolean booleanValue && booleanValue.booleanValue(); + + targetMethods.put(MethodReference.fromModel(methodModel), Pair.of(objectMethodType, includeSuper)); + } + } + } + } + + if (targetMethods.isEmpty()) { + return; + } + + // Collect field references + List fieldReferences = classModel.fields().stream() + .filter(fieldModel -> !fieldModel.flags().has(AccessFlag.STATIC) && !fieldModel.flags().has(AccessFlag.TRANSIENT)) + .map(FieldReference::fromModel) + .toList(); + ClassDesc classDesc = classModel.thisClass().asSymbol(); + ClassDesc superClassDesc = classModel.superclass().map(ClassEntry::asSymbol).orElse(null); + List methodsToGenerate = targetMethods.entrySet().stream() + .map(entry -> new ObjectMethodGeneration(classDesc, entry.getKey(), entry.getValue().left(), fieldReferences, entry.getValue().right() ? Optional.of(superClassDesc) : Optional.empty())) + .toList(); + + mapAdder.accept(methodsToGenerate); + } + + /// Requires that methods have the correct signature for the object method they wish to generate. + private static void checkMethodDesc(MethodModel methodModel, ObjectMethodType objectMethodType) { + MethodTypeDesc requiredDescriptor = switch (objectMethodType) { + case ObjectMethodType.EQUALS -> EQUALS_METHOD_DESC; + case ObjectMethodType.HASH_CODE -> HASH_CODE_METHOD_DESC; + case ObjectMethodType.TO_STRING -> TO_STRING_METHOD_DESC; + }; + + if (!methodModel.methodTypeSymbol().equals(requiredDescriptor)) { + throw new RuntimeException(String.format("Method '%s' has a mismatched descriptor! Expected: '%s'.", methodModel.methodName().stringValue(), requiredDescriptor.descriptorString())); + } + } +} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectProcessor.java b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectProcessor.java index 31332aec2c..bc3af30bb2 100644 --- a/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectProcessor.java +++ b/buildSrc/src/main/java/de/hysky/skyblocker/object/ObjectProcessor.java @@ -1,128 +1,36 @@ package de.hysky.skyblocker.object; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; import java.nio.file.Path; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.function.Consumer; -import java.util.stream.Stream; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodNode; - -import de.hysky.skyblocker.ClassReference; -import de.hysky.skyblocker.FieldReference; -import de.hysky.skyblocker.MethodReference; -import de.hysky.skyblocker.Pair; import de.hysky.skyblocker.Processor; public class ObjectProcessor { - private static final String EQUALS = "Lde/hysky/skyblocker/annotations/GenEquals;"; - private static final String HASH_CODE = "Lde/hysky/skyblocker/annotations/GenHashCode;"; - private static final String TO_STRING = "Lde/hysky/skyblocker/annotations/GenToString;"; - public static void apply() { + public static void apply(ClassFile context, Map classes) { long start = System.currentTimeMillis(); Map> methodsToGenerate = new HashMap<>(); - //Find all methods with the @GenEquals, @GenHashCode, or @GenToString annotations - findObjectGenerationMethods(methodsToGenerate); - - //Ensure that the method descriptors match, but not the names since it isn't strictly necessary that they match - validateObjectGenerationMethods(methodsToGenerate); - - //Inject the bytecode for the generated equals, hashCode, and toString implementations - injectObjectGenerationMethods(methodsToGenerate); - System.out.println("Injecting object methods took: " + (System.currentTimeMillis() - start) + "ms"); - } - - private static void findObjectGenerationMethods(Map> methodsToGenerate) { - Processor.forEachClass((path, inputStream) -> { - ClassNode classNode = new ClassNode(Opcodes.ASM9); - Processor.readClass(inputStream, classReader -> classNode); - - processClass(classNode, methods -> methodsToGenerate.put(path, methods)); - }); - } - - private static void processClass(ClassNode classNode, Consumer> mapAdder) { - Map> targetMethods = new HashMap<>(); - - //Check each method of the class for the annotations - for (MethodNode method : classNode.methods) { - MethodReference methodReference = new MethodReference(classNode.name, method.name, method.desc, false); - List annotations = Stream.of(method.invisibleAnnotations, method.visibleAnnotations) - .filter(Objects::nonNull) - .flatMap(List::stream) - .toList(); - - for (AnnotationNode annotation : annotations) { - ObjectMethodAnnotationVisitor annotationVisitor = new ObjectMethodAnnotationVisitor(); - annotation.accept(annotationVisitor); - - //The type of method to generate - ObjectMethodType objectMethodType = null; - - switch (annotation.desc) { - case EQUALS -> objectMethodType = ObjectMethodType.EQUALS; - case HASH_CODE -> objectMethodType = ObjectMethodType.HASH_CODE; - case TO_STRING -> objectMethodType = ObjectMethodType.TO_STRING; - } - - if (objectMethodType != null) { - //Ensure method is not abstract since this should not be used in interfaces - //It can however be native if you do not want a stub method body. - if ((method.access & Opcodes.ACC_ABSTRACT) != 0) throw new IllegalStateException("Methods that generate an Object method must not be abstract! Use the native modifier if you do not want a stub method body."); - - targetMethods.put(methodReference, new Pair<>(objectMethodType, annotationVisitor.getIncludeSuper())); - } - } + // Find all methods with the @GenEquals, @GenHashCode, or @GenToString annotations + for (Map.Entry entry : classes.entrySet()) { + ObjectMethodReader.readClass(entry.getValue(), list -> methodsToGenerate.put(entry.getKey(), list)); } - //Return early if there was no methods in the class that had our annotations - if (targetMethods.isEmpty()) return; - - //Collect field references - List fieldReferences = classNode.fields.stream() - .filter(field -> (field.access & Opcodes.ACC_STATIC) == 0 && (field.access & Opcodes.ACC_TRANSIENT) == 0) - .map(field -> new FieldReference(classNode.name, field.name, field.desc)) - .toList(); - - //Create the ObjectMethodGeneration instances - ClassReference classReference = new ClassReference(classNode.name); - ClassReference superClassReference = classNode.superName != null ? new ClassReference(classNode.superName) : null; - List methodsToGenerate = targetMethods.entrySet().stream() - .map(entry -> new ObjectMethodGeneration(entry.getKey(), entry.getValue().left(), classReference, fieldReferences, entry.getValue().right() ? superClassReference : null)) - .toList(); - - //Add the method generations to the map - mapAdder.accept(methodsToGenerate); - } - - private static void validateObjectGenerationMethods(Map> methodsToGenerate) { - List allGenerations = methodsToGenerate.values().stream() - .flatMap(List::stream) - .toList(); - - for (ObjectMethodGeneration generation : allGenerations) { - String requiredDescriptor = switch (generation.objectMethodType()) { - case ObjectMethodType.EQUALS -> "(Ljava/lang/Object;)Z"; - case ObjectMethodType.HASH_CODE -> "()I"; - case ObjectMethodType.TO_STRING -> "()Ljava/lang/String;"; - }; + // Inject the bytecode for the generated equals, hashCode, and toString implementations + for (Map.Entry> entry : methodsToGenerate.entrySet()) { + try { + byte[] classBytes = ObjectMethodInjector.transformClass(context, context.parse(entry.getKey()), entry.getValue()); - if (!generation.target().descriptor().equals(requiredDescriptor)) { - throw new RuntimeException(String.format("Method '%s' has a mismatched descriptor! Expected: '%s'.", generation.target().toString(), requiredDescriptor)); + Processor.writeClass(entry.getKey(), classBytes); + } catch (Exception e) { + throw new RuntimeException(e); } } - } - private static void injectObjectGenerationMethods(Map> methodsToGenerate) { - for (Map.Entry> entry : methodsToGenerate.entrySet()) { - Processor.writeClass(entry.getKey(), classWriter -> new ObjectInjectingClassVisitor(classWriter, entry.getValue())); - } + System.out.println("Injecting object methods took: " + (System.currentTimeMillis() - start) + "ms"); } } diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/object/package-info.java b/buildSrc/src/main/java/de/hysky/skyblocker/object/package-info.java new file mode 100644 index 0000000000..33f7be9de0 --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/object/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package de.hysky.skyblocker.object; + +import org.jspecify.annotations.NullMarked; diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/package-info.java b/buildSrc/src/main/java/de/hysky/skyblocker/package-info.java new file mode 100644 index 0000000000..cf854c5990 --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package de.hysky.skyblocker; + +import org.jspecify.annotations.NullMarked; diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/utils/FieldReference.java b/buildSrc/src/main/java/de/hysky/skyblocker/utils/FieldReference.java new file mode 100644 index 0000000000..cd3c02a1ce --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/utils/FieldReference.java @@ -0,0 +1,29 @@ +package de.hysky.skyblocker.utils; + +import java.lang.classfile.FieldModel; +import java.lang.constant.ClassDesc; + +/// Record representing some reference to a field. +/// +/// @param classDesc The descriptor of the class the field is declared in. +/// @param fieldName The name of the field (e.g. 'value'). +/// @param typeDesc The field's descriptor (e.g. 'Z', 'Ljava/lang/Object;'). +public record FieldReference(ClassDesc classDesc, String fieldName, ClassDesc typeDesc) { + + public static FieldReference fromModel(FieldModel fieldModel) { + // Expect that that the parent class is known + ClassDesc classDesc = fieldModel.parent().get().thisClass().asSymbol(); + String fieldName = fieldModel.fieldName().stringValue(); + ClassDesc typeDesc = fieldModel.fieldTypeSymbol(); + + return new FieldReference(classDesc, fieldName, typeDesc); + } + + public boolean matches(FieldModel fieldModel) { + return fieldModel.parent() + .map(classModel -> classModel.thisClass().asSymbol()) + .map(this.classDesc::equals).orElse(true) && + this.fieldName.equals(fieldModel.fieldName().stringValue()) && + this.typeDesc.equals(fieldModel.fieldTypeSymbol()); + } +} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/utils/MethodReference.java b/buildSrc/src/main/java/de/hysky/skyblocker/utils/MethodReference.java new file mode 100644 index 0000000000..8be07f657b --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/utils/MethodReference.java @@ -0,0 +1,36 @@ +package de.hysky.skyblocker.utils; + +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.reflect.AccessFlag; + +/// Record representing some reference to a method. +/// +/// @param classDesc The descriptor of the class in which this method is declared. +/// @param methodName The name of the method (e.g. 'main'). +/// @param typeDesc The type descriptor of the method (e.g. '(IJ)Z', '(Lnet/java/lang/Long;IZ)Ljava/lang/String;'). +/// @param itf Whether this method is declared in an interface. +public record MethodReference(ClassDesc classDesc, String methodName, MethodTypeDesc typeDesc, boolean itf) { + + public static MethodReference fromModel(MethodModel methodModel) { + // Expect that that the parent class is known + ClassModel parentClassModel = methodModel.parent().get(); + ClassDesc classDesc = parentClassModel.thisClass().asSymbol(); + String methodName = methodModel.methodName().stringValue(); + MethodTypeDesc typeDesc = methodModel.methodTypeSymbol(); + boolean itf = parentClassModel.flags().has(AccessFlag.INTERFACE); + + return new MethodReference(classDesc, methodName, typeDesc, itf); + } + + public boolean matches(MethodModel methodModel) { + return methodModel.parent() + .map(classModel -> classModel.thisClass().asSymbol()) + .map(this.classDesc::equals).orElse(true) && + this.methodName.equals(methodModel.methodName().stringValue()) && + this.typeDesc.equals(methodModel.methodTypeSymbol()) && + this.itf == methodModel.parent().map(classModel -> classModel.flags().has(AccessFlag.INTERFACE)).orElse(true); + } +} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/utils/Pair.java b/buildSrc/src/main/java/de/hysky/skyblocker/utils/Pair.java new file mode 100644 index 0000000000..d44f1d87ce --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/utils/Pair.java @@ -0,0 +1,9 @@ +package de.hysky.skyblocker.utils; + +/// An immutable pair of values. +public record Pair(L left, R right) { + + public static Pair of(L left, R right) { + return new Pair<>(left, right); + } +} diff --git a/buildSrc/src/main/java/de/hysky/skyblocker/utils/package-info.java b/buildSrc/src/main/java/de/hysky/skyblocker/utils/package-info.java new file mode 100644 index 0000000000..2bfa4e0ec0 --- /dev/null +++ b/buildSrc/src/main/java/de/hysky/skyblocker/utils/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package de.hysky.skyblocker.utils; + +import org.jspecify.annotations.NullMarked; diff --git a/checkstyle.xml b/checkstyle.xml index 13dae74ef3..e1a82ddefc 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -77,6 +77,10 @@ + + + + @@ -89,6 +93,9 @@ + + + diff --git a/gradle.properties b/gradle.properties index fa56fd7886..afeea762d4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,22 +3,22 @@ org.gradle.parallel=true org.gradle.configuration-cache=false # Fabric Properties (https://fabricmc.net/versions.html) -minecraft_version=1.21.11 +minecraft_version=26.1 loader_version=0.18.4 -loom_version=1.14-SNAPSHOT +loom_version=1.15-SNAPSHOT # Fabric API -fabric_api_version=0.140.0+1.21.11 +fabric_api_version=0.144.3+26.1 # Minecraft Mods ## Dandelion -dandelion_version=1.0.0-alpha.15+1.21.11 +dandelion_version=1.0.0-alpha.18+26.1 ## YACL (https://github.com/isXander/YetAnotherConfigLib) -yacl_version=3.8.1+1.21.11 +yacl_version=3.9.0+26.1 ## HM API (https://github.com/AzureAaron/hm-api) -hm_api_version=1.0.2+1.21.11 +hm_api_version=1.0.3+26.1 ## Mod Menu (https://modrinth.com/mod/modmenu/versions) -mod_menu_version = 17.0.0-alpha.1 +mod_menu_version = 18.0.0-alpha.6 ## REI (https://modrinth.com/mod/rei/versions?l=fabric) rei_version = 21.11.814 ## EMI (https://modrinth.com/mod/emi/versions) @@ -36,11 +36,11 @@ networth_calculator_version = 1.0.5 ## Legacy Item DFU (https://github.com/AzureAaron/legacy-item-dfu) legacy_item_dfu_version = 1.0.3+1.21.5 ## Fabric Language Kotlin -flk_version=1.13.7+kotlin.2.2.21 +flk_version=1.13.9+kotlin.2.3.10 # Other Libraries ## JGit (https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit) -jgit_version = 7.4.0.202509020913-r +jgit_version = 7.6.0.202603022253-r ## Apache Commons Math (https://mvnrepository.com/artifact/org.apache.commons/commons-math3) commons_math_version = 3.6.1 ## Apache Commons Text (https://mvnrepository.com/artifact/org.apache.commons/commons-text) @@ -48,9 +48,9 @@ commons_text_version = 1.15.0 # Miscellaneous Gradle Plugins ## Spotless (https://github.com/diffplug/spotless) -spotless_version=8.1.0 +spotless_version=8.3.0 ## Checkstyle (https://checkstyle.sourceforge.io) -checkstyle_version=12.2.0 +checkstyle_version=13.3.0 ## Mod Publish Plugin (https://github.com/modmuss50/mod-publish-plugin) mod_publish_plugin_version=1.1.0 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f8e1ee3125..d997cfc60f 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 23449a2b54..dbc3ce4a04 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index adff685a03..0262dcbd52 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/src/gametest/java/de/hysky/skyblocker/RoomDataTest.java b/src/gametest/java/de/hysky/skyblocker/RoomDataTest.java index cde2b4d128..31a93adde7 100644 --- a/src/gametest/java/de/hysky/skyblocker/RoomDataTest.java +++ b/src/gametest/java/de/hysky/skyblocker/RoomDataTest.java @@ -23,7 +23,7 @@ public class RoomDataTest implements FabricClientGameTest { @Override public void runTest(ClientGameTestContext clientGameTestContext) { - clientGameTestContext.waitFor((client) -> DungeonManager.isRoomsLoaded()); + clientGameTestContext.waitFor(_ -> DungeonManager.isRoomsLoaded()); clientGameTestContext.waitTicks(100); clientGameTestContext.runOnClient(this::testMain); } diff --git a/src/gametest/java/de/hysky/skyblocker/SkyblockerGameTest.java b/src/gametest/java/de/hysky/skyblocker/SkyblockerGameTest.java index aba5ef09b6..91458057b5 100644 --- a/src/gametest/java/de/hysky/skyblocker/SkyblockerGameTest.java +++ b/src/gametest/java/de/hysky/skyblocker/SkyblockerGameTest.java @@ -1,13 +1,20 @@ package de.hysky.skyblocker; +import de.hysky.skyblocker.debug.SnapshotDebug; +import de.hysky.skyblocker.skyblock.fancybars.FancyStatusBars; +import it.unimi.dsi.fastutil.Pair; import net.fabricmc.fabric.api.client.gametest.v1.FabricClientGameTest; import net.fabricmc.fabric.api.client.gametest.v1.context.ClientGameTestContext; +import net.fabricmc.fabric.api.client.gametest.v1.context.TestSingleplayerContext; +import net.fabricmc.fabric.api.client.gametest.v1.screenshot.TestScreenshotComparisonOptions; +import net.minecraft.client.gui.screens.worldselection.WorldCreationUiState; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.level.levelgen.presets.WorldPresets; @SuppressWarnings("UnstableApiUsage") public class SkyblockerGameTest implements FabricClientGameTest { @Override public void runTest(ClientGameTestContext context) { - /* try (TestSingleplayerContext singleplayer = context.worldBuilder().adjustSettings(worldCreator -> { worldCreator.setWorldType(new WorldCreationUiState.WorldTypeEntry(worldCreator.getSettings().worldgenLoadContext().lookupOrThrow(Registries.WORLD_PRESET).getOrThrow(WorldPresets.NORMAL))); worldCreator.setSeed(String.valueOf(SnapshotDebug.AARON_WORLD_SEED)); @@ -24,7 +31,7 @@ public void runTest(ClientGameTestContext context) { }); // Save the current fancy status bars config and reset it to default - var config = context.computeOnClient(client -> { + var config = context.computeOnClient(_ -> { var curConfig = FancyStatusBars.statusBars.entrySet().stream().map(e -> Pair.of(e.getKey(), e.getValue().toJson())).toList(); int[] counts = new int[7]; @@ -39,15 +46,15 @@ public void runTest(ClientGameTestContext context) { }); // Take a screenshot and compare it - singleplayer.getClientWorld().waitForChunksRender(); + singleplayer.getClientLevel().waitForChunksRender(); context.assertScreenshotEquals(TestScreenshotComparisonOptions.of("skyblocker_render").saveWithFileName("skyblocker_render")); // Restore the fancy status bars config - context.runOnClient(client -> { + context.runOnClient(_ -> { config.forEach(pair -> FancyStatusBars.statusBars.get(pair.key()).loadFromJson(pair.value())); FancyStatusBars.placeBarsInPositioner(); FancyStatusBars.updatePositions(false); }); - }*/ + } } } diff --git a/src/gametest/resources/fabric.mod.json b/src/gametest/resources/fabric.mod.json index 369718de4c..f6253f313d 100644 --- a/src/gametest/resources/fabric.mod.json +++ b/src/gametest/resources/fabric.mod.json @@ -16,8 +16,7 @@ "entrypoints": { "fabric-client-gametest": [ "de.hysky.skyblocker.RoomDataTest", - "de.hysky.skyblocker.SkyblockerConfigTest", - "de.hysky.skyblocker.SkyblockerGameTest" + "de.hysky.skyblocker.SkyblockerConfigTest" ] } } diff --git a/src/gametest/resources/templates/skyblocker_config.png b/src/gametest/resources/templates/skyblocker_config.png index 64311b7666..8656bea508 100644 Binary files a/src/gametest/resources/templates/skyblocker_config.png and b/src/gametest/resources/templates/skyblocker_config.png differ diff --git a/src/main/java/de/hysky/skyblocker/DisableAll.java b/src/main/java/de/hysky/skyblocker/DisableAll.java index ec44e873a0..a4f01a5046 100644 --- a/src/main/java/de/hysky/skyblocker/DisableAll.java +++ b/src/main/java/de/hysky/skyblocker/DisableAll.java @@ -8,7 +8,7 @@ import de.hysky.skyblocker.config.ConfigNullFieldsFix; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Constants; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.ClientCommands; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.ChatFormatting; @@ -35,10 +35,10 @@ public static void init() { private static long confirmAllowedUntil; private static void registerCommand(CommandDispatcher dispatcher, net.minecraft.commands.CommandBuildContext registryAccess) { - dispatcher.register(ClientCommandManager.literal(SkyblockerMod.NAMESPACE) - .then(ClientCommandManager.literal("disableAll") + dispatcher.register(ClientCommands.literal(SkyblockerMod.NAMESPACE) + .then(ClientCommands.literal("disableAll") .executes(DisableAll::confirmMessage) - .then(ClientCommandManager.literal("confirm") + .then(ClientCommands.literal("confirm") .executes(DisableAll::disableAll))) ); } diff --git a/src/main/java/de/hysky/skyblocker/DisableAllPopup.java b/src/main/java/de/hysky/skyblocker/DisableAllPopup.java index c26c08162e..ccd3a908f1 100644 --- a/src/main/java/de/hysky/skyblocker/DisableAllPopup.java +++ b/src/main/java/de/hysky/skyblocker/DisableAllPopup.java @@ -28,7 +28,7 @@ public void open(Screen parent) { Component confirmPrefix = Component.translatable("text.skyblocker.confirm").withColor(CommonColors.RED).withStyle(style -> style.withBold(true)); Component confirmComponent = new CountdownComponent(DELAY_S, TimeUnit.SECONDS, confirmPrefix, Style.EMPTY); PopupScreen.Builder builder = new PopupScreen.Builder(parent, Component.translatable("skyblocker.disableAll.popup.title")) - .setMessage(Component.translatable("skyblocker.disableAll.popup.warning", Component.translatable("skyblocker.disableAll.popup.seriousWarning").withColor(CommonColors.SOFT_RED))) + .addMessage(Component.translatable("skyblocker.disableAll.popup.warning", Component.translatable("skyblocker.disableAll.popup.seriousWarning").withColor(CommonColors.SOFT_RED))) .addButton(confirmComponent, this::tryReset) .addButton(CommonComponents.GUI_CANCEL, PopupScreen::onClose); diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerCreditsScreen.java b/src/main/java/de/hysky/skyblocker/SkyblockerCreditsScreen.java index 5cd99514cc..c36cdb9fa3 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerCreditsScreen.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerCreditsScreen.java @@ -20,12 +20,12 @@ import de.hysky.skyblocker.utils.scheduler.Scheduler; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.ClientCommands; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.loader.api.metadata.Person; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.input.KeyEvent; import net.minecraft.client.renderer.RenderPipelines; @@ -72,9 +72,9 @@ protected SkyblockerCreditsScreen(@Nullable Screen parent) { @Init public static void initClass() { - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { - dispatcher.register(ClientCommandManager.literal(SkyblockerMod.NAMESPACE) - .then(ClientCommandManager.literal("credits") + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> { + dispatcher.register(ClientCommands.literal(SkyblockerMod.NAMESPACE) + .then(ClientCommands.literal("credits") .executes(Scheduler.queueOpenScreenCommand(() -> new SkyblockerCreditsScreen(null))))); }); } @@ -251,9 +251,9 @@ private void addCreditsLine(Component text, boolean centred, boolean narratable) } @Override - public void render(GuiGraphics graphics, int mouseX, int mouseY, float a) { - super.render(graphics, mouseX, mouseY, a); - this.renderVignette(graphics); + public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractRenderState(graphics, mouseX, mouseY, a); + this.extractVignette(graphics); this.scroll = Math.max(0f, this.scroll + a * this.scrollSpeed); int logoX = this.width / 2 - 128; @@ -264,7 +264,7 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float a) { graphics.pose().translate(0f, yOffs); graphics.nextStratum(); - this.renderLogo(graphics, this.width, logoY); + this.extractLogo(graphics, this.width, logoY); int yPos = logoY + 100; for (int i = 0; i < this.lines.size(); i++) { @@ -280,9 +280,9 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float a) { FormattedCharSequence line = this.lines.get(i); if (this.centredLines.contains(i)) { - graphics.drawCenteredString(this.font, line, logoX + 128, yPos, CommonColors.WHITE); + graphics.centeredText(this.font, line, logoX + 128, yPos, CommonColors.WHITE); } else { - graphics.drawString(this.font, line, logoX, yPos, CommonColors.WHITE); + graphics.text(this.font, line, logoX, yPos, CommonColors.WHITE); } } @@ -292,19 +292,19 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float a) { graphics.pose().popMatrix(); } - private void renderVignette(GuiGraphics graphics) { + private void extractVignette(GuiGraphicsExtractor graphics) { graphics.blit(RenderPipelines.VIGNETTE, VIGNETTE, 0, 0, 0f, 0f, this.width, this.height, this.width, this.height); } - private void renderLogo(GuiGraphics graphics, int width, int heightOffset) { + private void extractLogo(GuiGraphicsExtractor graphics, int width, int heightOffset) { int logoX = width / 2 - 128; graphics.blit(RenderPipelines.GUI_TEXTURED, LOGO, logoX, heightOffset, 0f, 0f, 256, 64, 256, 64, CommonColors.WHITE); } @Override - protected void renderMenuBackground(GuiGraphics graphics, int x, int y, int width, int height) { + protected void extractMenuBackground(GuiGraphicsExtractor graphics, int x, int y, int width, int height) { float v = this.scroll * 0.5f; - Screen.renderMenuBackgroundTexture(graphics, Screen.MENU_BACKGROUND, 0, 0, 0f, v, width, height); + Screen.extractMenuBackgroundTexture(graphics, Screen.MENU_BACKGROUND, 0, 0, 0f, v, width, height); } @Override diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerScreen.java b/src/main/java/de/hysky/skyblocker/SkyblockerScreen.java index 8dd36a9f4a..f78c2449f0 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerScreen.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerScreen.java @@ -5,10 +5,10 @@ import de.hysky.skyblocker.skyblock.Tips; import de.hysky.skyblocker.utils.FunUtils; import de.hysky.skyblocker.utils.scheduler.Scheduler; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.command.v2.ClientCommands; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.MultiLineTextWidget; import net.minecraft.client.gui.components.StringWidget; @@ -57,8 +57,8 @@ public SkyblockerScreen() { @Init public static void initClass() { - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { - dispatcher.register(ClientCommandManager.literal(SkyblockerMod.NAMESPACE) + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> { + dispatcher.register(ClientCommands.literal(SkyblockerMod.NAMESPACE) .executes(Scheduler.queueOpenScreenCommand(SkyblockerScreen::new))); }); } @@ -72,24 +72,24 @@ protected void init() { gridWidget.defaultCellSetting().alignHorizontallyCenter(); GridLayout.RowHelper adder = gridWidget.createRowHelper(2); - adder.addChild(Button.builder(CONFIGURATION_TEXT, button -> this.openConfig()).width(BUTTON_WIDTH).build(), 2); + adder.addChild(Button.builder(CONFIGURATION_TEXT, _ -> this.openConfig()).width(BUTTON_WIDTH).build(), 2); adder.addChild(Button.builder(SOURCE_TEXT, ConfirmLinkScreen.confirmLink(this, "https://github.com/SkyblockerMod/Skyblocker")).width(HALF_BUTTON_WIDTH).build()); adder.addChild(Button.builder(REPORT_BUGS_TEXT, ConfirmLinkScreen.confirmLink(this, "https://github.com/SkyblockerMod/Skyblocker/issues")).width(HALF_BUTTON_WIDTH).build()); adder.addChild(Button.builder(WEBSITE_TEXT, ConfirmLinkScreen.confirmLink(this, "https://hysky.de/")).width(HALF_BUTTON_WIDTH).build()); adder.addChild(Button.builder(TRANSLATE_TEXT, ConfirmLinkScreen.confirmLink(this, "https://translate.hysky.de/")).width(HALF_BUTTON_WIDTH).build()); adder.addChild(Button.builder(MODRINTH_TEXT, ConfirmLinkScreen.confirmLink(this, "https://modrinth.com/mod/skyblocker-liap")).width(HALF_BUTTON_WIDTH).build()); adder.addChild(Button.builder(DISCORD_TEXT, ConfirmLinkScreen.confirmLink(this, "https://discord.gg/aNNJHQykck")).width(HALF_BUTTON_WIDTH).build()); - adder.addChild(Button.builder(CommonComponents.GUI_DONE, button -> this.onClose()).width(BUTTON_WIDTH).build(), 2); + adder.addChild(Button.builder(CommonComponents.GUI_DONE, _ -> this.onClose()).width(BUTTON_WIDTH).build(), 2); GridLayout footerGridWidget = this.layout.addToFooter(new GridLayout()).spacing(SPACING).rowSpacing(0); footerGridWidget.defaultCellSetting().alignHorizontallyCenter(); GridLayout.RowHelper footerAdder = footerGridWidget.createRowHelper(2); footerAdder.addChild(tip = new MultiLineTextWidget(Tips.nextTip(), this.font).setCentered(true).setMaxWidth((int) (this.width * 0.7)), 2); - footerAdder.addChild(Button.builder(Component.translatable("skyblocker.tips.previous"), button -> { + footerAdder.addChild(Button.builder(Component.translatable("skyblocker.tips.previous"), _ -> { tip.setMessage(Tips.previousTip()); layout.arrangeElements(); }).build()); - footerAdder.addChild(Button.builder(Component.translatable("skyblocker.tips.next"), button -> { + footerAdder.addChild(Button.builder(Component.translatable("skyblocker.tips.next"), _ -> { tip.setMessage(Tips.nextTip()); layout.arrangeElements(); }).build()); @@ -109,8 +109,8 @@ private void openConfig() { } @Override - public void render(GuiGraphics context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); + public void extractRenderState(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { + super.extractRenderState(context, mouseX, mouseY, delta); } private static class IconTextWidget extends StringWidget { @@ -122,7 +122,7 @@ private static class IconTextWidget extends StringWidget { } @Override - public void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delta) { + public void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float delta) { Component text = this.getMessage(); Font textRenderer = this.getFont(); @@ -137,8 +137,8 @@ public void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delt int iconX = x - 34; int iconY = y - 13; - context.drawString(textRenderer, orderedText, x, y, CommonColors.WHITE); - context.blit(RenderPipelines.GUI_TEXTURED, this.icon, iconX, iconY, 0, 0, 32, 32, 32, 32); + graphics.text(textRenderer, orderedText, x, y, CommonColors.WHITE); + graphics.blit(RenderPipelines.GUI_TEXTURED, this.icon, iconX, iconY, 0, 0, 32, 32, 32, 32); } private FormattedCharSequence trim(Component text, int width) { diff --git a/src/main/java/de/hysky/skyblocker/UpdateNotifications.java b/src/main/java/de/hysky/skyblocker/UpdateNotifications.java index adef4993ac..fb2a3d928f 100644 --- a/src/main/java/de/hysky/skyblocker/UpdateNotifications.java +++ b/src/main/java/de/hysky/skyblocker/UpdateNotifications.java @@ -63,7 +63,7 @@ public class UpdateNotifications { @Init public static void init() { - ClientLifecycleEvents.CLIENT_STARTED.register(client -> loaded = CONFIG.init()); + ClientLifecycleEvents.CLIENT_STARTED.register(_ -> loaded = CONFIG.init()); SkyblockEvents.JOIN.register(() -> Objects.requireNonNull(loaded).thenRunAsync(UpdateNotifications::tryCheckForNewVersion, Minecraft.getInstance())); } @@ -103,7 +103,7 @@ private static void checkForNewVersion() { return; } - MINECRAFT.player.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.updateNotifications.newUpdateMessage", versionText)), false); + MINECRAFT.player.sendSystemMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.updateNotifications.newUpdateMessage", versionText))); SystemToast.add(MINECRAFT.getToastManager(), TOAST_TYPE, Component.translatable("skyblocker.updateNotifications.newUpdateToast.title"), Component.translatableEscape("skyblocker.updateNotifications.newUpdateToast.description", newVersion.version())); }); } @@ -130,7 +130,7 @@ private static void introduceNewUpdate() { .withClickEvent(new ClickEvent.RunCommand("/skyblocker config " + versionTagString))); Component newVersionText = Component.translatable("skyblocker.updateNotifications.configureNewVersion", SkyblockerMod.VERSION, configureText); - MINECRAFT.player.displayClientMessage(Constants.PREFIX.get().append(newVersionText), false); + MINECRAFT.player.sendSystemMessage(Constants.PREFIX.get().append(newVersionText)); setConfig(config -> config.withNewestVersionUsed(currentModVersion)); } catch (Exception e) { LOGGER.error("[Skyblocker Update Notifications] Failed to introduce the new update!", e); @@ -185,7 +185,7 @@ private static DataResult parseVersion(String version) { try { return DataResult.success(SemanticVersion.parse(formattedVersion)); - } catch (VersionParsingException e) { + } catch (VersionParsingException _) { return DataResult.error(() -> "Failed to parse semantic version from string: " + formattedVersion); } } diff --git a/src/main/java/de/hysky/skyblocker/compatibility/CaxtonCompatibility.java b/src/main/java/de/hysky/skyblocker/compatibility/CaxtonCompatibility.java index a8c10bbea1..bf43a3a778 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/CaxtonCompatibility.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/CaxtonCompatibility.java @@ -5,7 +5,7 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.util.FormattedCharSequence; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; @@ -33,7 +33,7 @@ public final class CaxtonCompatibility { return lookup.findStatic( clazz, "drawText4Way", - MethodType.methodType(void.class, GuiGraphics.class, Font.class, FormattedCharSequence.class, float.class, float.class, int.class, int.class)); + MethodType.methodType(void.class, GuiGraphicsExtractor.class, Font.class, FormattedCharSequence.class, float.class, float.class, int.class, int.class)); } catch (NoSuchMethodException | IllegalAccessException e) { LOGGER.error("[Skyblocker Caxton Compat] Could not find drawText4Way method", e); return null; @@ -60,10 +60,10 @@ private static Optional getCaxtonPipeline(String name) { private static final MethodHandle HANDLE = createHandle(); private static boolean errored = false; - public static boolean drawOutlinedText(GuiGraphics context, FormattedCharSequence text, float x, float y, int color, int outlineColor) { + public static boolean drawOutlinedText(GuiGraphicsExtractor graphics, FormattedCharSequence text, float x, float y, int color, int outlineColor) { if (HANDLE == null || errored) return false; try { - HANDLE.invoke(context, Minecraft.getInstance().font, text, x, y, color, outlineColor); + HANDLE.invoke(graphics, Minecraft.getInstance().font, text, x, y, color, outlineColor); } catch (Throwable e) { LOGGER.error("[Skyblocker Caxton Compat] Could not invoke drawText4Way", e); errored = true; diff --git a/src/main/java/de/hysky/skyblocker/compatibility/IrisCompatibility.java b/src/main/java/de/hysky/skyblocker/compatibility/IrisCompatibility.java index 0f7d3011d9..a54ec16d30 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/IrisCompatibility.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/IrisCompatibility.java @@ -53,7 +53,7 @@ private static void assignPipeline(RenderPipeline pipeline, String irisProgramNa Objects.requireNonNull(GET_IRIS_PROGRAM, "Iris Program handle must be present to assign a pipeline."); REGISTER_PIPELINE.invoke(GET_IRIS_API.invoke(), pipeline, GET_IRIS_PROGRAM.invoke(irisProgramName)); - } catch (IllegalStateException ignored) { + } catch (IllegalStateException _) { //The pipeline was probably already registered } catch (Throwable e) { LOGGER.error("[Skyblocker Iris Compatibility] Failed to assign pipeline {} to {}.", pipeline.getLocation(), irisProgramName, e); @@ -67,7 +67,7 @@ private static MethodHandle getIrisApiHandle() { MethodType type = MethodType.methodType(irisApiClass); return lookup.findStatic(irisApiClass, "getInstance", type); - } catch (Exception e) { + } catch (Exception _) { return null; } } @@ -80,7 +80,7 @@ private static MethodHandle getRegisterPipelineHandle() { MethodType type = MethodType.methodType(void.class, RenderPipeline.class, irisProgramClass); return lookup.findVirtual(irisApiClass, "assignPipeline", type); - } catch (Exception e) { + } catch (Exception _) { return null; } } @@ -93,7 +93,7 @@ private static MethodHandle getIrisProgramHandle() { MethodHandle enumValueOf = lookup.findStatic(Enum.class, "valueOf", type); return MethodHandles.insertArguments(enumValueOf, 0, irisProgramClass); - } catch (Exception e) { + } catch (Exception _) { return null; } } diff --git a/src/main/java/de/hysky/skyblocker/compatibility/ModernUICompatibility.java b/src/main/java/de/hysky/skyblocker/compatibility/ModernUICompatibility.java index 067e2acbba..c8f2866b82 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/ModernUICompatibility.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/ModernUICompatibility.java @@ -4,7 +4,7 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.util.FormattedCharSequence; import org.joml.Matrix3x2fStack; import org.slf4j.Logger; @@ -45,7 +45,7 @@ private static boolean isTextEngineEnabled() { // text engine changes require game reboot so it's good enough to check only once private static final boolean IS_TEXT_ENGINE_ENABLED = isTextEngineEnabled(); - public static boolean drawOutlinedText(GuiGraphics context, FormattedCharSequence text, FormattedCharSequence outlineText, int x, int y, int color, int outlineColor) { + public static boolean extractOutlinedText(GuiGraphicsExtractor context, FormattedCharSequence text, FormattedCharSequence outlineText, int x, int y, int color, int outlineColor) { if (!IS_TEXT_ENGINE_ENABLED) return false; final float offset = 0.5f; // default value of ModernTextRenderer.sOutlineOffset @@ -56,38 +56,38 @@ public static boolean drawOutlinedText(GuiGraphics context, FormattedCharSequenc // https://github.com/BloCamLimb/ModernUI-MC/blob/3.12.0.4/common/src/main/java/icyllis/modernui/mc/text/mixin/MixinContextualBar.java pose.pushMatrix() .translate(offset, 0); - context.drawString(textRenderer, outlineText, x, y, outlineColor, false); + context.text(textRenderer, outlineText, x, y, outlineColor, false); pose.popMatrix(); pose.pushMatrix() .translate(offset, offset); - context.drawString(textRenderer, outlineText, x, y, outlineColor, false); + context.text(textRenderer, outlineText, x, y, outlineColor, false); pose.popMatrix(); pose.pushMatrix() .translate(offset, -offset); - context.drawString(textRenderer, outlineText, x, y, outlineColor, false); + context.text(textRenderer, outlineText, x, y, outlineColor, false); pose.popMatrix(); pose.pushMatrix() .translate(-offset, 0); - context.drawString(textRenderer, outlineText, x, y, outlineColor, false); + context.text(textRenderer, outlineText, x, y, outlineColor, false); pose.popMatrix(); pose.pushMatrix() .translate(-offset, offset); - context.drawString(textRenderer, outlineText, x, y, outlineColor, false); + context.text(textRenderer, outlineText, x, y, outlineColor, false); pose.popMatrix(); pose.pushMatrix() .translate(-offset, -offset); - context.drawString(textRenderer, outlineText, x, y, outlineColor, false); + context.text(textRenderer, outlineText, x, y, outlineColor, false); pose.popMatrix(); pose.pushMatrix() .translate(0, offset); - context.drawString(textRenderer, outlineText, x, y, outlineColor, false); + context.text(textRenderer, outlineText, x, y, outlineColor, false); pose.popMatrix(); pose.pushMatrix() .translate(0, -offset); - context.drawString(textRenderer, outlineText, x, y, outlineColor, false); + context.text(textRenderer, outlineText, x, y, outlineColor, false); pose.popMatrix(); - context.drawString(textRenderer, text, x, y, color, false); + context.text(textRenderer, text, x, y, color, false); return true; } } diff --git a/src/main/java/de/hysky/skyblocker/compatibility/ResourcePackCompatibility.java b/src/main/java/de/hysky/skyblocker/compatibility/ResourcePackCompatibility.java index 81a38fb392..ab1840a9dc 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/ResourcePackCompatibility.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/ResourcePackCompatibility.java @@ -27,7 +27,7 @@ public class ResourcePackCompatibility { @Init(priority = -1) public static void init() { - ResourceLoader.get(PackType.CLIENT_RESOURCES).registerReloader(SkyblockerMod.id("pack_compatibility_listener"), new ReloadListener()); + ResourceLoader.get(PackType.CLIENT_RESOURCES).registerReloadListener(SkyblockerMod.id("pack_compatibility_listener"), new ReloadListener()); } private static final class ReloadListener extends SimplePreparableReloadListener>> { diff --git a/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java b/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java index 82c54dde56..9adda572ff 100644 --- a/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java @@ -1,11 +1,11 @@ package de.hysky.skyblocker.config; -import de.hysky.skyblocker.utils.render.HudHelper; +import de.hysky.skyblocker.utils.render.GuiHelper; import de.hysky.skyblocker.utils.render.gui.AbstractWidget; import it.unimi.dsi.fastutil.ints.IntIntMutablePair; import java.awt.Color; import java.util.List; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.network.chat.Component; @@ -60,10 +60,10 @@ protected void init() { } @Override - public final void render(GuiGraphics context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); - renderWidget(context, widgets, delta); - context.drawCenteredString(font, "Right Click To Reset Position", width / 2, height / 2, Color.GRAY.getRGB()); + public final void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float delta) { + super.extractRenderState(graphics, mouseX, mouseY, delta); + extractRenderState(graphics, widgets, delta); + graphics.centeredText(font, "Right Click To Reset Position", width / 2, height / 2, Color.GRAY.getRGB()); } /** @@ -72,9 +72,9 @@ public final void render(GuiGraphics context, int mouseX, int mouseY, float delt * @param context the context to render in * @param widgets the widgets to render */ - protected void renderWidget(GuiGraphics context, List widgets, float delta) { + protected void extractRenderState(GuiGraphicsExtractor graphics, List widgets, float delta) { for (AbstractWidget widget : widgets) { - widget.render(context, -1, -1, delta); + widget.extractRenderState(graphics, -1, -1, delta); } } @@ -91,7 +91,7 @@ public final boolean mouseDragged(MouseButtonEvent click, double offsetX, double public final boolean mouseClicked(MouseButtonEvent click, boolean doubled) { if (click.button() == 0) { for (AbstractWidget widget : widgets) { - if (HudHelper.pointIsInArea(click.x(), click.y(), widget.getX() + getWidgetXOffset(widget), widget.getY(), widget.getX() + getWidgetXOffset(widget) + widget.getWidth(), widget.getY() + widget.getHeight())) { + if (GuiHelper.pointIsInArea(click.x(), click.y(), widget.getX() + getWidgetXOffset(widget), widget.getY(), widget.getX() + getWidgetXOffset(widget) + widget.getWidth(), widget.getY() + widget.getHeight())) { draggingWidget = widget; mouseClickRelativeX = click.x() - widget.getX() - getWidgetXOffset(widget); mouseClickRelativeY = click.y() - widget.getY(); diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java index b410a9fd0c..a6f52a2136 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java @@ -30,6 +30,7 @@ import de.hysky.skyblocker.utils.scheduler.Scheduler; import net.azureaaron.dandelion.api.ConfigManager; import net.azureaaron.dandelion.api.DandelionConfigScreen; +import net.azureaaron.dandelion.api.PlatformLinks; import net.azureaaron.dandelion.api.patching.ConfigPatch; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; @@ -52,8 +53,8 @@ import java.util.function.Consumer; import java.util.function.UnaryOperator; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; import org.slf4j.Logger; public class SkyblockerConfigManager { @@ -82,11 +83,11 @@ public static void init() { dataFix(CONFIG_FILE, CONFIG_DIR.resolve("skyblocker.json.old")); CONFIG_MANAGER.load(); - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(configLiteral("config")).then(configLiteral("options")))); - ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(configLiteral("config")).then(configLiteral("options")))); + ScreenEvents.AFTER_INIT.register((client, screen, _, _) -> { if (get().uiAndVisuals.showConfigButton && screen instanceof ContainerScreen genericContainerScreen && screen.getTitle().getString().equals("SkyBlock Menu")) { - Screens.getButtons(screen).add(Button - .builder(Component.literal("\uD83D\uDD27"), buttonWidget -> client.setScreen(createGUI(screen))) + Screens.getWidgets(screen).add(Button + .builder(Component.literal("\uD83D\uDD27"), _ -> client.setScreen(createGUI(screen))) .bounds(((AbstractContainerScreenAccessor) genericContainerScreen).getX() + ((AbstractContainerScreenAccessor) genericContainerScreen).getImageWidth() - 16, ((AbstractContainerScreenAccessor) genericContainerScreen).getY() + 4, 12, 12) .tooltip(Tooltip.create(Component.translatable("skyblocker.config.title", Component.translatable("skyblocker.config.title.settings")))) .build()); @@ -139,6 +140,10 @@ public static Screen createGUI(@Nullable Screen parent, String search) { .category(MiscCategory.create(defaults, config)) .categoryIf(Debug.debugEnabled(), DebugCategory.create(defaults, config)) .search(search) + .platformLinks(PlatformLinks.createBuilder() + .link(Component.literal("GitHub"), PlatformLinks.GITHUB_ICON, "https://github.com/SkyblockerMod/Skyblocker") + .link(Component.literal("Modrinth"), PlatformLinks.MODRINTH_ICON, "https://modrinth.com/mod/skyblocker-liap") + .build()) ).generateScreen(parent, get().misc.configBackend); } @@ -163,7 +168,7 @@ public static void reload() { */ private static LiteralArgumentBuilder configLiteral(String name) { return literal(name).executes(Scheduler.queueOpenScreenCommand(() -> createGUI(null))) - .then(argument("option", StringArgumentType.greedyString()).executes((ctx) -> Scheduler.queueOpenScreen(createGUI(null, ctx.getArgument("option", String.class))))); + .then(argument("option", StringArgumentType.greedyString()).executes(ctx -> Scheduler.queueOpenScreen(createGUI(null, ctx.getArgument("option", String.class))))); } public static void dataFix(Path configDir, Path backupDir) { diff --git a/src/main/java/de/hysky/skyblocker/config/backup/ConfigBackupManager.java b/src/main/java/de/hysky/skyblocker/config/backup/ConfigBackupManager.java index b998db2fd9..c3d55c4d6d 100644 --- a/src/main/java/de/hysky/skyblocker/config/backup/ConfigBackupManager.java +++ b/src/main/java/de/hysky/skyblocker/config/backup/ConfigBackupManager.java @@ -38,7 +38,7 @@ public static void init() { } }, Executors.newVirtualThreadPerTaskExecutor()); - ClientLifecycleEvents.CLIENT_STOPPING.register(client -> backupConfig()); + ClientLifecycleEvents.CLIENT_STOPPING.register(_ -> backupConfig()); } public static void backupConfig() { diff --git a/src/main/java/de/hysky/skyblocker/config/backup/ConfigBackupScreen.java b/src/main/java/de/hysky/skyblocker/config/backup/ConfigBackupScreen.java index 241d41d227..624c3cb4fe 100644 --- a/src/main/java/de/hysky/skyblocker/config/backup/ConfigBackupScreen.java +++ b/src/main/java/de/hysky/skyblocker/config/backup/ConfigBackupScreen.java @@ -17,7 +17,7 @@ import java.util.List; import java.util.Set; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.ObjectSelectionList; @@ -68,7 +68,7 @@ protected void init() { detailsWidget.refreshScrollAmount(); addRenderableWidget(detailsWidget); - Button restoreBtn = Button.builder(Component.translatable("skyblocker.config.general.backup.restore"), b -> { + Button restoreBtn = Button.builder(Component.translatable("skyblocker.config.general.backup.restore"), _ -> { Path selected = listWidget.getSelectedPath(); if (selected != null) { assert minecraft != null; @@ -99,7 +99,7 @@ protected void init() { }).size(90, 20).pos(width / 2 - 95, height - 28).build(); addRenderableWidget(restoreBtn); - Button done = Button.builder(CommonComponents.GUI_DONE, b -> onClose()).size(90, 20).pos(width / 2 + 5, height - 28).build(); + Button done = Button.builder(CommonComponents.GUI_DONE, _ -> onClose()).size(90, 20).pos(width / 2 + 5, height - 28).build(); addRenderableWidget(done); StringWidget titleWidget = new StringWidget(title, font); @@ -137,7 +137,7 @@ void updateEntries() { for (Path backup : backups) { addEntry(new BackupEntry(backup)); } - } catch (IOException e) { + } catch (IOException _) { // ignored } } @@ -156,8 +156,8 @@ private class BackupEntry extends ObjectSelectionList.Entry { } @Override - public void renderContent(GuiGraphics context, int mouseX, int mouseY, boolean hovered, float deltaTicks) { - context.drawCenteredString(font, path.getFileName().toString(), this.getContentXMiddle(), this.getY() + 7, 0xFFFFFFFF); + public void extractContent(GuiGraphicsExtractor context, int mouseX, int mouseY, boolean hovered, float deltaTicks) { + context.centeredText(font, path.getFileName().toString(), this.getContentXMiddle(), this.getY() + 7, 0xFFFFFFFF); if (isMouseOver(mouseX, mouseY)) context.requestCursor(CursorTypes.POINTING_HAND); } @@ -250,9 +250,9 @@ private void formatJson(String key, JsonElement element, String path, int indent } @Override - protected void renderScrollbar(GuiGraphics context, int mouseX, int mouseY) { - super.renderScrollbar(context, mouseX, mouseY); - if (scrollbarVisible()) { + protected void extractScrollbar(GuiGraphicsExtractor context, int mouseX, int mouseY) { + super.extractScrollbar(context, mouseX, mouseY); + if (this.scrollable()) { int scrollBarX = scrollBarX(); int listWidgetY = getY(); int totalHeight = height + maxScrollAmount(); @@ -292,12 +292,12 @@ public List narratables() { } @Override - public void renderContent(GuiGraphics context, int mouseX, int mouseY, boolean hovered, float deltaTicks) { + public void extractContent(GuiGraphicsExtractor graphics, int mouseX, int mouseY, boolean hovered, float deltaTicks) { int color = 0xFFFFFFFF; if (path != null && changedPaths.contains(path)) { color = 0xFFFFFF55; } - context.drawString(font, text, this.getX() + 2, this.getY() + 2, color, false); + graphics.text(font, text, this.getX() + 2, this.getY() + 2, color, false); } } } diff --git a/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java index ccd550f434..ae07eb7ffb 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java @@ -87,7 +87,7 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .option(ButtonOption.createBuilder() .name(Component.translatable("skyblocker.config.foraging.galatea.enableTreeBreakHud")) .prompt(Component.translatable("text.skyblocker.open")) - .action((screen) -> Minecraft.getInstance().setScreen(new WidgetsConfigurationScreen(Location.GALATEA, TreeBreakProgressHud.getInstance().getInternalID(), screen))) + .action(screen -> Minecraft.getInstance().setScreen(new WidgetsConfigurationScreen(Location.GALATEA, TreeBreakProgressHud.getInstance().getInternalID(), screen))) .build()) .option(Option.createBuilder() .name(Component.translatable("skyblocker.config.foraging.galatea.enableTunerSolver")) diff --git a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java index 8a25b3fbf5..03af5e9935 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -34,7 +34,7 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .option(ButtonOption.createBuilder() .name(Component.translatable("skyblocker.skyblockerScreen")) .prompt(Component.translatable("text.skyblocker.open")) - .action(screen -> Minecraft.getInstance().setScreen(new SkyblockerScreen())) + .action(_ -> Minecraft.getInstance().setScreen(new SkyblockerScreen())) .build()) // Disable All @@ -248,7 +248,7 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .binding(defaults.general.itemTooltip.enableCraftingCost, () -> config.general.itemTooltip.enableCraftingCost, newValue -> config.general.itemTooltip.enableCraftingCost = newValue) - .listener((ignored, updateType) -> { + .listener((_, updateType) -> { if (updateType == UpdateType.VALUE_CHANGE) CraftPriceTooltip.clearCache(); }) .controller(ConfigUtils.createEnumController()) diff --git a/src/main/java/de/hysky/skyblocker/config/categories/OtherLocationsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/OtherLocationsCategory.java index c081a58875..625fac3bca 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/OtherLocationsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/OtherLocationsCategory.java @@ -173,7 +173,7 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .option(ButtonOption.createBuilder() .name(Component.translatable("skyblocker.config.otherLocations.end.resetName")) .prompt(Component.translatable("skyblocker.config.otherLocations.end.resetText")) - .action(screen -> TheEnd.PROFILES_STATS.put(TheEnd.EndStats.EMPTY.get())) + .action(_ -> TheEnd.PROFILES_STATS.put(TheEnd.EndStats.EMPTY.get())) .build()) .option(Option.createBuilder() .name(Component.translatable("skyblocker.config.otherLocations.end.muteEndermanSounds")) diff --git a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java index f8adf23f86..a93ada099b 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java @@ -445,7 +445,7 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .option(ButtonOption.createBuilder() .name(Component.translatable("skyblocker.config.uiAndVisuals.bars.openScreen")) .prompt(Component.translatable("text.skyblocker.open")) - .action(screen -> Minecraft.getInstance().setScreen(new StatusBarsConfigScreen())) + .action(_ -> Minecraft.getInstance().setScreen(new StatusBarsConfigScreen())) .build()) .option(Option.createBuilder() .name(Component.translatable("skyblocker.config.uiAndVisuals.bars.intelligenceDisplay")) diff --git a/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java index bf2ee283c0..291abe74d3 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java @@ -175,8 +175,14 @@ public static class BlockBreakPrediction { */ @Deprecated public enum DwarvenHudStyle { - SIMPLE, FANCY, CLASSIC; + @Deprecated + SIMPLE, + @Deprecated + FANCY, + @Deprecated + CLASSIC; + @Deprecated @Override public String toString() { return switch (this) { diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java index 6e0323c06d..5b519e8c88 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java @@ -301,12 +301,16 @@ public enum IntelligenceDisplay { @SuppressWarnings("DeprecatedIsStillUsed") @Deprecated public static class LegacyBarPositions { + @Deprecated public LegacyBarPosition healthBarPosition = LegacyBarPosition.LAYER1; + @Deprecated public LegacyBarPosition manaBarPosition = LegacyBarPosition.LAYER1; + @Deprecated public LegacyBarPosition defenceBarPosition = LegacyBarPosition.RIGHT; + @Deprecated public LegacyBarPosition experienceBarPosition = LegacyBarPosition.LAYER2; } diff --git a/src/main/java/de/hysky/skyblocker/config/screens/powdertracker/ItemTickList.java b/src/main/java/de/hysky/skyblocker/config/screens/powdertracker/ItemTickList.java index 9b7bb193cc..72420c39b3 100644 --- a/src/main/java/de/hysky/skyblocker/config/screens/powdertracker/ItemTickList.java +++ b/src/main/java/de/hysky/skyblocker/config/screens/powdertracker/ItemTickList.java @@ -4,7 +4,7 @@ import java.util.Collection; import java.util.List; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Checkbox; import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -63,7 +63,7 @@ public ItemTickList init() { ItemTickEntry entry = new ItemTickEntry( Checkbox.builder(Component.nullToEmpty(item.toString()), minecraft.font) .selected(whitelist == filters.contains(item)) - .onValueChange((checkbox1, checked) -> { + .onValueChange((_, checked) -> { if (whitelist) { if (checked) filters.add(item); else filters.remove(item); @@ -93,13 +93,13 @@ public void setChecked(boolean checked) { } @Override - public void renderContent(GuiGraphics context, int mouseX, int mouseY, boolean hovered, float deltaTicks) { + public void extractContent(GuiGraphicsExtractor graphics, int mouseX, int mouseY, boolean hovered, float deltaTicks) { for (Checkbox child : children) { child.setX(this.getX()); child.setY(this.getY()); child.setWidth(this.getWidth()); child.setHeight(this.getHeight()); - child.render(context, mouseX, mouseY, deltaTicks); + child.extractRenderState(graphics, mouseX, mouseY, deltaTicks); } } diff --git a/src/main/java/de/hysky/skyblocker/config/screens/powdertracker/PowderFilterConfigScreen.java b/src/main/java/de/hysky/skyblocker/config/screens/powdertracker/PowderFilterConfigScreen.java index 3532c9695c..dc9758be25 100644 --- a/src/main/java/de/hysky/skyblocker/config/screens/powdertracker/PowderFilterConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/config/screens/powdertracker/PowderFilterConfigScreen.java @@ -29,9 +29,9 @@ public PowderFilterConfigScreen(@Nullable Screen parent, List allItems) @Override protected void init() { - addRenderableOnly((context, mouseX, mouseY, delta) -> { + addRenderableOnly((context, _, _, _) -> { assert minecraft != null; - context.drawCenteredString(minecraft.font, Component.translatable("skyblocker.config.mining.crystalHollows.powderTrackerFilter.screenTitle").withStyle(ChatFormatting.BOLD), width / 2, (32 - minecraft.font.lineHeight) / 2, CommonColors.WHITE); + context.text(minecraft.font, Component.translatable("skyblocker.config.mining.crystalHollows.powderTrackerFilter.screenTitle").withStyle(ChatFormatting.BOLD), width / 2, (32 - minecraft.font.lineHeight) / 2, CommonColors.WHITE); }); ItemTickList itemTickList = addRenderableWidget(new ItemTickList<>(Minecraft.getInstance(), width, height - 96, 32, 24, filters, allItems).init()); //Grid code gratuitously stolen from WaypointsScreen. Same goes for the y and heights above. @@ -39,16 +39,16 @@ protected void init() { gridWidget.defaultCellSetting().paddingHorizontal(5).paddingVertical(2); GridLayout.RowHelper adder = gridWidget.createRowHelper(2); - adder.addChild(Button.builder(Component.translatable("text.skyblocker.reset"), button -> { + adder.addChild(Button.builder(Component.translatable("text.skyblocker.reset"), _ -> { filters.clear(); itemTickList.clearAndInit(); }).build()); - adder.addChild(Button.builder(Component.translatable("text.skyblocker.undo"), button -> { + adder.addChild(Button.builder(Component.translatable("text.skyblocker.undo"), _ -> { filters.clear(); filters.addAll(SkyblockerConfigManager.get().mining.crystalHollows.powderTrackerFilter); itemTickList.clearAndInit(); }).build()); - adder.addChild(Button.builder(CommonComponents.GUI_DONE, button -> { + adder.addChild(Button.builder(CommonComponents.GUI_DONE, _ -> { saveFilters(); onClose(); }) diff --git a/src/main/java/de/hysky/skyblocker/debug/Debug.java b/src/main/java/de/hysky/skyblocker/debug/Debug.java index 747cfbba53..a849b9f99d 100644 --- a/src/main/java/de/hysky/skyblocker/debug/Debug.java +++ b/src/main/java/de/hysky/skyblocker/debug/Debug.java @@ -19,7 +19,7 @@ import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.fabricmc.fabric.api.client.keymapping.v1.KeyMappingHelper; import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.fabricmc.fabric.api.client.screen.v1.ScreenKeyboardEvents; import net.fabricmc.loader.api.FabricLoader; @@ -44,7 +44,7 @@ import java.util.List; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; public class Debug { private static final Logger LOGGER = LogUtils.getLogger(); @@ -71,9 +71,9 @@ public static boolean webSocketDebug() { public static void init() { if (!debugEnabled()) return; SnapshotDebug.init(); - KeyMapping dumpNearbyEntitiesKey = KeyBindingHelper.registerKeyBinding(new KeyMapping("key.skyblocker.debug.dumpNearbyEntities", GLFW.GLFW_KEY_I, SkyblockerMod.KEYBINDING_CATEGORY)); - KeyMapping dumpHoveredItemKey = KeyBindingHelper.registerKeyBinding(new KeyMapping("key.skyblocker.debug.dumpHoveredItem", GLFW.GLFW_KEY_U, SkyblockerMod.KEYBINDING_CATEGORY)); - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register( + KeyMapping dumpNearbyEntitiesKey = KeyMappingHelper.registerKeyMapping(new KeyMapping("key.skyblocker.debug.dumpNearbyEntities", GLFW.GLFW_KEY_I, SkyblockerMod.KEYBINDING_CATEGORY)); + KeyMapping dumpHoveredItemKey = KeyMappingHelper.registerKeyMapping(new KeyMapping("key.skyblocker.debug.dumpHoveredItem", GLFW.GLFW_KEY_U, SkyblockerMod.KEYBINDING_CATEGORY)); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> dispatcher.register( literal(SkyblockerMod.NAMESPACE).then(literal("debug") .then(dumpPlayersCommand()) .then(ItemUtils.dumpHeldItemCommand()) @@ -99,21 +99,21 @@ public static void init() { return writeView.buildResult(); }) .map(NbtUtils::toPrettyComponent) - .forEach(text -> client.player.displayClientMessage(text, false)); + .forEach(text -> client.player.sendSystemMessage(text)); keyDown = true; } else if (!dumpNearbyEntitiesKey.consumeClick() && keyDown) { keyDown = false; } }); - ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + ScreenEvents.BEFORE_INIT.register((client, screen, _, _) -> { if (!(screen instanceof AbstractContainerScreen handledScreen)) return; - ScreenKeyboardEvents.afterKeyPress(screen).register((_screen, keyInput) -> { + ScreenKeyboardEvents.afterKeyPress(screen).register((_, keyInput) -> { Slot focusedSlot = ((AbstractContainerScreenAccessor) handledScreen).getFocusedSlot(); if (dumpHoveredItemKey.matches(keyInput) && client.player != null && focusedSlot != null && focusedSlot.hasItem()) { if (!keyInput.hasShiftDown()) { - client.player.displayClientMessage(Constants.PREFIX.get().append("Hovered Item: ").append(SkyblockerConfigManager.get().debug.dumpFormat.format(focusedSlot.getItem())), false); + client.player.sendSystemMessage(Constants.PREFIX.get().append("Hovered Item: ").append(SkyblockerConfigManager.get().debug.dumpFormat.format(focusedSlot.getItem()))); } else { - client.player.displayClientMessage(Constants.PREFIX.get().append("Held Item NW Calcs: ").append(Component.literal(SkyblockerMod.GSON_COMPACT.toJson(Calculation.LIST_CODEC.encodeStart(JsonOps.INSTANCE, NetworthCalculator.getItemNetworth(focusedSlot.getItem()).calculations()).getOrThrow()))), false); + client.player.sendSystemMessage(Constants.PREFIX.get().append("Held Item NW Calcs: ").append(Component.literal(SkyblockerMod.GSON_COMPACT.toJson(Calculation.LIST_CODEC.encodeStart(JsonOps.INSTANCE, NetworthCalculator.getItemNetworth(focusedSlot.getItem()).calculations()).getOrThrow())))); } } }); @@ -123,7 +123,7 @@ public static void init() { private static LiteralArgumentBuilder dumpPlayersCommand() { return literal("dumpPlayers") .executes(context -> { - context.getSource().getWorld().players().forEach(player -> context.getSource().sendFeedback(Component.nullToEmpty("'" + player.getName().getString() + "'"))); + context.getSource().getLevel().players().forEach(player -> context.getSource().sendFeedback(Component.nullToEmpty("'" + player.getName().getString() + "'"))); return Command.SINGLE_SUCCESS; }); } @@ -149,7 +149,7 @@ private static LiteralArgumentBuilder toggleWebSocket private static LiteralArgumentBuilder dumpArmorStandHeadTextures() { return literal("dumpArmorStandHeadTextures") .executes(context -> { - List armorStands = context.getSource().getWorld().getEntitiesOfClass(ArmorStand.class, context.getSource().getPlayer().getBoundingBox().inflate(8d), EntitySelector.ENTITY_NOT_BEING_RIDDEN); + List armorStands = context.getSource().getLevel().getEntitiesOfClass(ArmorStand.class, context.getSource().getPlayer().getBoundingBox().inflate(8d), EntitySelector.ENTITY_NOT_BEING_RIDDEN); for (ArmorStand armorStand : armorStands) { Iterable equippedItems = ItemUtils.getArmor(armorStand); @@ -167,7 +167,7 @@ private static LiteralArgumentBuilder dumpBiome() { return literal("dumpBiome") .executes(context -> { FabricClientCommandSource source = context.getSource(); - Holder biome = source.getWorld().getBiome(source.getPlayer().blockPosition()); + Holder biome = source.getLevel().getBiome(source.getPlayer().blockPosition()); if (biome != null && biome.value() != null) { String biomeData = Biome.DIRECT_CODEC.encodeStart(JsonOps.INSTANCE, biome.value()) @@ -198,7 +198,7 @@ private static LiteralArgumentBuilder dumpActionBar() private static LiteralArgumentBuilder auditMixins() { return literal("auditMixins") - .executes(context -> { + .executes(_ -> { MixinEnvironment.getCurrentEnvironment().audit(); return Command.SINGLE_SUCCESS; diff --git a/src/main/java/de/hysky/skyblocker/debug/SnapshotDebug.java b/src/main/java/de/hysky/skyblocker/debug/SnapshotDebug.java index 2705610b3f..03835f2221 100644 --- a/src/main/java/de/hysky/skyblocker/debug/SnapshotDebug.java +++ b/src/main/java/de/hysky/skyblocker/debug/SnapshotDebug.java @@ -1,6 +1,6 @@ package de.hysky.skyblocker.debug; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import net.minecraft.SharedConstants; import net.minecraft.client.Minecraft; @@ -26,7 +26,7 @@ public static boolean isInSnapshot() { static void init() { if (Debug.debugEnabled()) { - WorldRenderExtractionCallback.EVENT.register(SnapshotDebug::extractRendering); + LevelRenderExtractionCallback.EVENT.register(SnapshotDebug::extractRendering); } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java index 3d9c532c75..f81201c24d 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java @@ -21,19 +21,16 @@ import de.hysky.skyblocker.skyblock.item.tooltip.CompactorDeletorPreview; import de.hysky.skyblocker.skyblock.item.wikilookup.WikiLookupManager; import de.hysky.skyblocker.skyblock.museum.MuseumItemCache; -import de.hysky.skyblocker.skyblock.museum.MuseumManager; -import de.hysky.skyblocker.skyblock.quicknav.QuickNav; -import de.hysky.skyblocker.skyblock.quicknav.QuickNavButton; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.container.ContainerSolver; import de.hysky.skyblocker.utils.container.ContainerSolverManager; import de.hysky.skyblocker.utils.container.StackDisplayModifier; -import de.hysky.skyblocker.utils.render.HudHelper; +import de.hysky.skyblocker.utils.render.GuiHelper; import net.fabricmc.fabric.api.client.screen.v1.Screens; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; @@ -44,7 +41,7 @@ import net.minecraft.resources.Identifier; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.Slot; import net.minecraft.world.inventory.tooltip.TooltipComponent; import net.minecraft.world.item.Item; @@ -119,56 +116,11 @@ public abstract class AbstractContainerScreenMixin quickNavButtons; protected AbstractContainerScreenMixin(Component title) { super(title); } - @Inject(method = "init", at = @At("RETURN")) - private void skyblocker$initQuickNav(CallbackInfo ci) { - if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().quickNav.enableQuickNav && minecraft != null && minecraft.player != null && !minecraft.player.isCreative()) { - for (QuickNavButton quickNavButton : quickNavButtons = QuickNav.init(getTitle().getString().trim())) { - addWidget(quickNavButton); - } - } - } - - @SuppressWarnings("unused") - @Inject(method = "init", at = @At("TAIL")) - private void skyblocker$initMuseumOverlay(CallbackInfo ci) { - if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.museumOverlay && minecraft != null && minecraft.player != null && getTitle().getString().contains("Museum")) { - int overlayWidth = MuseumManager.BACKGROUND_WIDTH; // width of the overlay - int spacing = MuseumManager.SPACING; // space between inventory and overlay - - // Default: center inventory - int inventoryX = (this.width - this.imageWidth) / 2; - - // If overlay would go off the right edge, shift inventory left - if (inventoryX + this.imageWidth + spacing + overlayWidth > this.width) { - inventoryX = this.width - (this.imageWidth + overlayWidth + spacing); - if (inventoryX < 0) inventoryX = 0; - } - this.leftPos = inventoryX; - - new MuseumManager(this, this.leftPos, this.topPos, this.imageWidth); - } - } - - @WrapOperation(method = "renderBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;renderBg(Lnet/minecraft/client/gui/GuiGraphics;FII)V")) - private void skyblocker$DrawMuseumOverlayBackground(AbstractContainerScreen instance, GuiGraphics context, float delta, int mouseX, int mouseY, Operation original) { - if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.museumOverlay && minecraft != null && minecraft.player != null && getTitle().getString().contains("Museum")) { - // Custom museum overlay background drawing - int rows = 6; - context.blit(RenderPipelines.GUI_TEXTURED, GENERIC_CONTAINER_TEXTURE, this.leftPos, this.topPos, 0.0F, 0.0F, this.imageWidth, rows * 18 + 17, 256, 256); - context.blit(RenderPipelines.GUI_TEXTURED, GENERIC_CONTAINER_TEXTURE, this.leftPos, this.topPos + rows * 18 + 17, 0.0F, 126.0F, this.imageWidth, 96, 256, 256); - } else { - // Call vanilla - original.call(instance, context, delta, mouseX, mouseY); - } - } - @Inject(at = @At("HEAD"), method = "keyPressed") public void skyblocker$keyPressed(KeyEvent input, CallbackInfoReturnable cir) { if (this.minecraft != null && this.minecraft.player != null && this.hoveredSlot != null && !input.isEscape() && !this.minecraft.options.keyInventory.matches(input) && Utils.isOnSkyblock()) { @@ -192,7 +144,7 @@ protected AbstractContainerScreenMixin(Component title) { public boolean skyblocker$passThroughSearchFieldUnfocusedClicks(boolean superClicked, MouseButtonEvent click, boolean doubled) { //Handle Search Field clicks - as of 1.21.4 the game will only send clicks to the selected element rather than trying to send one to each and stopping when the first returns true (if any). if (!superClicked) { - Optional searchField = Screens.getButtons(this).stream() + Optional searchField = Screens.getWidgets(this).stream() .filter(InventorySearch.SearchTextFieldWidget.class::isInstance) .findFirst(); @@ -204,44 +156,17 @@ protected AbstractContainerScreenMixin(Component title) { return superClicked; } - /** - * Draws the unselected tabs in front of the background blur, but behind the main inventory, similar to creative inventory tabs - */ - @Inject(method = "renderBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;renderBg(Lnet/minecraft/client/gui/GuiGraphics;FII)V")) - private void skyblocker$drawUnselectedQuickNavButtons(GuiGraphics context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - if (quickNavButtons != null) for (QuickNavButton quickNavButton : quickNavButtons) { - // Render the button behind the main inventory background if it's not toggled or if it's still fading in - if (!quickNavButton.toggled() || quickNavButton.getAlpha() < 255) { - quickNavButton.setRenderInFront(false); - quickNavButton.render(context, mouseX, mouseY, delta); - } - } - } - - /** - * Draws the selected tab in front of the background blur and the main inventory, similar to creative inventory tabs - */ - @Inject(method = "renderBackground", at = @At("RETURN")) - private void skyblocker$drawSelectedQuickNavButtons(GuiGraphics context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - if (quickNavButtons != null) for (QuickNavButton quickNavButton : quickNavButtons) { - if (quickNavButton.toggled()) { - quickNavButton.setRenderInFront(true); - quickNavButton.render(context, mouseX, mouseY, delta); - } - } - } - @SuppressWarnings("unchecked") - @Inject(method = "renderTooltip", at = @At("HEAD")) - private void skyblocker$beforeTooltipDrawn(CallbackInfo ci, @Local(argsOnly = true) GuiGraphics context) { - ContainerSolverManager.onDraw(context, (AbstractContainerScreen) (Object) this, this.menu.slots); + @Inject(method = "extractTooltip", at = @At("HEAD")) + private void skyblocker$beforeTooltipExtracted(CallbackInfo ci, @Local(name = "graphics") GuiGraphicsExtractor graphics) { + ContainerSolverManager.onExtract(graphics, (AbstractContainerScreen) (Object) this, this.menu.slots); } @SuppressWarnings("DataFlowIssue") // makes intellij be quiet about this.focusedSlot maybe being null. It's already null checked in mixined method. - @WrapOperation(method = "renderTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphics;setTooltipForNextFrame(Lnet/minecraft/client/gui/Font;Ljava/util/List;Ljava/util/Optional;IILnet/minecraft/resources/Identifier;)V")) - private void skyblocker$drawMouseOverTooltip( - GuiGraphics context, + @WrapOperation(method = "extractTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;setTooltipForNextFrame(Lnet/minecraft/client/gui/Font;Ljava/util/List;Ljava/util/Optional;IILnet/minecraft/resources/Identifier;)V")) + private void skyblocker$extractMouseOverTooltip( + GuiGraphicsExtractor graphics, Font textRenderer, List text, Optional data, @@ -249,7 +174,7 @@ protected AbstractContainerScreenMixin(Component title) { int y, Identifier texture, Operation original, - @Local(ordinal = 0) ItemStack stack + @Local(name = "item") ItemStack stack ) { // Hide tooltips from items that have been visually replaced by a container solver with air (since the Slot#hasStack still passes) if (ContainerSolverManager.getCurrentSolver() instanceof StackDisplayModifier && stack.isEmpty()) { @@ -257,7 +182,7 @@ protected AbstractContainerScreenMixin(Component title) { } if (!Utils.isOnSkyblock() || text.isEmpty()) { - original.call(context, textRenderer, text, data, x, y, texture); + original.call(graphics, textRenderer, text, data, x, y, texture); return; } @@ -269,29 +194,29 @@ protected AbstractContainerScreenMixin(Component title) { } // Backpack Preview - boolean shiftDown = SkyblockerConfigManager.get().uiAndVisuals.backpackPreviewWithoutShift ^ HudHelper.hasShiftDown(); - if (shiftDown && getTitle().getString().equals("Storage") && hoveredSlot.container != minecraft.player.getInventory() && BackpackPreview.renderPreview(context, this, hoveredSlot.getContainerSlot(), x, y)) { + boolean shiftDown = SkyblockerConfigManager.get().uiAndVisuals.backpackPreviewWithoutShift ^ GuiHelper.hasShiftDown(); + if (shiftDown && getTitle().getString().equals("Storage") && hoveredSlot.container != minecraft.player.getInventory() && BackpackPreview.extractPreview(graphics, this, hoveredSlot.getContainerSlot(), x, y)) { return; } // Compactor Preview if (SkyblockerConfigManager.get().uiAndVisuals.compactorDeletorPreview) { Matcher matcher = CompactorDeletorPreview.NAME.matcher(stack.getSkyblockId()); - if (matcher.matches() && CompactorDeletorPreview.drawPreview(context, stack, getTooltipFromContainerItem(stack), matcher.group("type"), matcher.group("size"), x, y)) { + if (matcher.matches() && CompactorDeletorPreview.extractPreview(graphics, stack, getTooltipFromContainerItem(stack), matcher.group("type"), matcher.group("size"), x, y)) { return; } } - original.call(context, textRenderer, text, data, x, y, texture); + original.call(graphics, textRenderer, text, data, x, y, texture); } - @ModifyVariable(method = "renderTooltip", at = @At(value = "STORE")) + @ModifyVariable(method = "extractTooltip", at = @At(value = "STORE")) private ItemStack skyblocker$modifyTooltipDisplayStack(ItemStack stack) { return skyblocker$modifyDisplayStack(hoveredSlot, stack, ContainerSolverManager.getCurrentSolver()); } - @ModifyVariable(method = "renderSlot", at = @At(value = "LOAD", ordinal = 3), ordinal = 0) - private ItemStack skyblocker$modifyDisplayStack(ItemStack stack, @Local(argsOnly = true) Slot slot) { + @ModifyVariable(method = "extractSlot", at = @At(value = "LOAD", ordinal = 3), ordinal = 0) + private ItemStack skyblocker$modifyDisplayStack(ItemStack stack, @Local(name = "slot") Slot slot) { return skyblocker$modifyDisplayStack(slot, stack, ContainerSolverManager.getCurrentSolver()); } @@ -307,10 +232,10 @@ protected AbstractContainerScreenMixin(Component title) { * The naming of this method in yarn is half true, its mostly to handle slot/item interactions (which are mouse or keyboard clicks) * For example, using the drop key bind while hovering over an item will invoke this method to drop the players item * - * @implNote This runs before {@link AbstractContainerMenu#clicked(int, int, ClickType, net.minecraft.world.entity.player.Player)} + * @implNote This runs before {@link AbstractContainerMenu#clicked(int, int, ContainerInput, net.minecraft.world.entity.player.Player)} */ - @Inject(method = "slotClicked(Lnet/minecraft/world/inventory/Slot;IILnet/minecraft/world/inventory/ClickType;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/MultiPlayerGameMode;handleInventoryMouseClick(IIILnet/minecraft/world/inventory/ClickType;Lnet/minecraft/world/entity/player/Player;)V"), cancellable = true) - private void skyblocker$onSlotClick(Slot slot, int slotId, int button, ClickType actionType, CallbackInfo ci) { + @Inject(method = "slotClicked(Lnet/minecraft/world/inventory/Slot;IILnet/minecraft/world/inventory/ContainerInput;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/MultiPlayerGameMode;handleContainerInput(IIILnet/minecraft/world/inventory/ContainerInput;Lnet/minecraft/world/entity/player/Player;)V"), cancellable = true) + private void skyblocker$onSlotClick(Slot slot, int slotId, int button, ContainerInput containerInput, CallbackInfo ci) { if (!Utils.isOnSkyblock()) return; // Item Protection @@ -342,7 +267,7 @@ protected AbstractContainerScreenMixin(Component title) { } // Item Protection // When you click your drop key while hovering over an item - if (actionType == ClickType.THROW && ItemProtection.isItemProtected(stack)) { + if (containerInput == ContainerInput.THROW && ItemProtection.isItemProtected(stack)) { ci.cancel(); return; } @@ -402,32 +327,32 @@ protected AbstractContainerScreenMixin(Component title) { } } - @Inject(method = "renderSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphics;renderItem(Lnet/minecraft/world/item/ItemStack;III)V")) - private void skyblocker$drawOnItem(CallbackInfo ci, @Local(argsOnly = true) GuiGraphics context, @Local(argsOnly = true) Slot slot) { + @Inject(method = "extractSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;item(Lnet/minecraft/world/item/ItemStack;III)V")) + private void skyblocker$drawOnItem(CallbackInfo ci, @Local(name = "graphics") GuiGraphicsExtractor graphics, @Local(name = "slot") Slot slot) { if (Utils.isOnSkyblock()) { - ItemBackgroundManager.drawBackgrounds(slot.getItem(), context, slot.x, slot.y); + ItemBackgroundManager.drawBackgrounds(slot.getItem(), graphics, slot.x, slot.y); } // Item Protection if (ItemProtection.isItemProtected(slot.getItem())) { - context.blit(RenderPipelines.GUI_TEXTURED, ItemProtection.ITEM_PROTECTION_TEX, slot.x, slot.y, 0, 0, 16, 16, 16, 16); + graphics.blit(RenderPipelines.GUI_TEXTURED, ItemProtection.ITEM_PROTECTION_TEX, slot.x, slot.y, 0, 0, 16, 16, 16, 16); } // Search - darken non-matching slots if (InventorySearch.isSearching() && !InventorySearch.slotMatches(slot)) { - context.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, 0x88_000000); + graphics.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, 0x88_000000); } } - @Inject(method = "renderSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphics;renderItemDecorations(Lnet/minecraft/client/gui/Font;Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V")) - private void skyblocker$drawSlotText(CallbackInfo ci, @Local(argsOnly = true) GuiGraphics context, @Local(argsOnly = true) Slot slot) { + @Inject(method = "extractSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;itemDecorations(Lnet/minecraft/client/gui/Font;Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V")) + private void skyblocker$drawSlotText(CallbackInfo ci, @Local(name = "graphics") GuiGraphicsExtractor graphics, @Local(name = "slot") Slot slot) { if (Utils.isOnSkyblock()) { - SlotTextManager.renderSlotText(context, font, slot); + SlotTextManager.extractSlotText(graphics, font, slot); } } - @WrapWithCondition(method = "renderLabels", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphics;drawString(Lnet/minecraft/client/gui/Font;Lnet/minecraft/network/chat/Component;IIIZ)V", ordinal = 0)) - private boolean skyblocker$hideChestName(GuiGraphics instance, Font font, Component component, int i, int j, int k, boolean bl) { + @WrapWithCondition(method = "extractLabels", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;text(Lnet/minecraft/client/gui/Font;Lnet/minecraft/network/chat/Component;IIIZ)V", ordinal = 0)) + private boolean skyblocker$hideChestName(GuiGraphicsExtractor graphics, Font font, Component component, int x, int y, int colour, boolean shadow) { return !ChestValue.hideChestNameLabel; } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/AbstractSignEditScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/AbstractSignEditScreenMixin.java index 50c6b10149..46c8a5393f 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/AbstractSignEditScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/AbstractSignEditScreenMixin.java @@ -1,6 +1,5 @@ package de.hysky.skyblocker.mixins; - import com.llamalad7.mixinextras.sugar.Local; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.bazaar.BazaarQuickQuantities; @@ -8,7 +7,7 @@ import de.hysky.skyblocker.skyblock.speedpreset.SpeedPresets; import de.hysky.skyblocker.utils.Utils; import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen; @@ -48,20 +47,20 @@ protected AbstractSignEditScreenMixin(Component title) { } } - @Inject(method = "render", at = @At("HEAD")) - private void skyblocker$render(CallbackInfo ci, @Local(argsOnly = true) GuiGraphics context) { + @Inject(method = "extractRenderState", at = @At("HEAD")) + private void skyblocker$extractRenderStateSign(CallbackInfo ci, @Local(name = "graphics") GuiGraphicsExtractor graphics) { if (Utils.isOnSkyblock()) { var config = SkyblockerConfigManager.get(); if (isSpeedInputSign() && config.general.speedPresets.enableSpeedPresets) { var presets = SpeedPresets.getInstance(); if (presets.hasPreset(messages[0])) { - context.drawCenteredString(this.font, Component.literal(String.format("%s » %d", messages[0], presets.getPreset(messages[0]))).withStyle(ChatFormatting.GREEN), - context.guiWidth() / 2, 55, 0xFFFFFFFF); + graphics.centeredText(this.font, Component.literal(String.format("%s » %d", messages[0], presets.getPreset(messages[0]))).withStyle(ChatFormatting.GREEN), + graphics.guiWidth() / 2, 55, 0xFFFFFFFF); } } //if the sign is being used to enter number send it to the sign calculator else if (isInputSign() && config.uiAndVisuals.inputCalculator.enabled) { - SignCalculator.renderCalculator(context, messages[0], context.guiWidth() / 2, 55); + SignCalculator.extractCalculator(graphics, messages[0], graphics.guiWidth() / 2, 55); } } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/BossHealthOverlayMixin.java b/src/main/java/de/hysky/skyblocker/mixins/BossHealthOverlayMixin.java index 6719511aa8..abb08f9413 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/BossHealthOverlayMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/BossHealthOverlayMixin.java @@ -3,7 +3,7 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.slayers.SlayerBossBar; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.BossHealthOverlay; import net.minecraft.client.gui.components.LerpingBossEvent; import net.minecraft.util.CommonColors; @@ -22,17 +22,17 @@ public abstract class BossHealthOverlayMixin { private Minecraft minecraft; @Shadow - protected abstract void drawBar(GuiGraphics context, int x, int y, BossEvent bossBar); + protected abstract void extractBar(GuiGraphicsExtractor graphics, int x, int y, BossEvent bossBar); - @Inject(method = "render", at = @At("HEAD"), cancellable = true) - private void onRender(GuiGraphics context, CallbackInfo ci) { + @Inject(method = "extractRenderState", at = @At("HEAD"), cancellable = true) + private void onRender(GuiGraphicsExtractor graphics, CallbackInfo ci) { if (SkyblockerConfigManager.get().slayers.displayBossbar && SlayerBossBar.shouldRenderBossBar()) { LerpingBossEvent bossBar = SlayerBossBar.updateBossBar(); int textWidth = this.minecraft.font.width(bossBar.getName()); - context.drawString(this.minecraft.font, bossBar.getName(), context.guiWidth() / 2 - textWidth / 2, 3, CommonColors.WHITE); + graphics.text(this.minecraft.font, bossBar.getName(), graphics.guiWidth() / 2 - textWidth / 2, 3, CommonColors.WHITE); - this.drawBar(context, (context.guiWidth() / 2) - 91, 12, bossBar); + this.extractBar(graphics, (graphics.guiWidth() / 2) - 91, 12, bossBar); ci.cancel(); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/CameraMixin.java b/src/main/java/de/hysky/skyblocker/mixins/CameraMixin.java index 21d87a0161..27232b814c 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/CameraMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/CameraMixin.java @@ -26,8 +26,6 @@ public class CameraMixin { } } - - return original; } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/ClientLevelMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ClientLevelMixin.java index f37bc67a68..c4326b926a 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ClientLevelMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ClientLevelMixin.java @@ -21,7 +21,7 @@ public abstract class ClientLevelMixin implements BlockGetter { @Inject(method = "setServerVerifiedBlockState", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;II)Z")) - private void skyblocker$beforeBlockUpdate(CallbackInfo ci, @Local(argsOnly = true) BlockPos pos, @Share("old") LocalRef oldState) { + private void skyblocker$beforeBlockUpdate(CallbackInfo ci, @Local(name = "pos") BlockPos pos, @Share("old") LocalRef oldState) { oldState.set(getBlockState(pos)); } @@ -30,19 +30,19 @@ public abstract class ClientLevelMixin implements BlockGetter { * (e.g. store it in a field/list/map) make sure to duplicate it via {@link BlockPos#immutable()}. */ @Inject(method = "setServerVerifiedBlockState", at = @At("RETURN")) - private void skyblocker$afterBlockUpdate(CallbackInfo ci, @Local(argsOnly = true) BlockPos pos, @Local(argsOnly = true) BlockState state, @Share("old") LocalRef oldState) { + private void skyblocker$afterBlockUpdate(CallbackInfo ci, @Local(name = "pos") BlockPos pos, @Local(name = "blockState") BlockState state, @Share("old") LocalRef oldState) { WorldEvents.BLOCK_STATE_UPDATE.invoker().onBlockStateUpdate(pos, oldState.get(), state); } @Inject(method = "playSeededSound(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/Holder;Lnet/minecraft/sounds/SoundSource;FFJ)V", at = @At("HEAD"), cancellable = true) - private void skyblocker$allowSoundsFromEntity(CallbackInfo ci, @Local(argsOnly = true) Holder sound) { + private void skyblocker$allowSoundsFromEntity(CallbackInfo ci, @Local(name = "sound") Holder sound) { if (!PlaySoundEvents.ALLOW_SOUND.invoker().allowSound(sound.value())) { ci.cancel(); } } @Inject(method = "playSound(DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FFZJ)V", at = @At("HEAD"), cancellable = true) - private void skyblocker$allowSounds(CallbackInfo ci, @Local(argsOnly = true) SoundEvent sound) { + private void skyblocker$allowSounds(CallbackInfo ci, @Local(name = "sound") SoundEvent sound) { if (!PlaySoundEvents.ALLOW_SOUND.invoker().allowSound(sound)) { ci.cancel(); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/ClientPacketListenerMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ClientPacketListenerMixin.java index fbec95c904..86e12ab5a6 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ClientPacketListenerMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ClientPacketListenerMixin.java @@ -71,7 +71,7 @@ protected ClientPacketListenerMixin(Minecraft client, Connection connection, Com } @Inject(method = "handleSetEntityData", at = @At("TAIL")) - private void skyblocker$onEntityTrackerUpdate(ClientboundSetEntityDataPacket packet, CallbackInfo ci, @Local Entity entity) { + private void skyblocker$onEntityTrackerUpdate(ClientboundSetEntityDataPacket packet, CallbackInfo ci, @Local(name = "entity") Entity entity) { if (!(entity instanceof ArmorStand armorStandEntity)) return; SlayerManager.checkSlayerBoss(armorStandEntity); @@ -112,7 +112,7 @@ protected ClientPacketListenerMixin(Minecraft client, Connection connection, Com } @Inject(method = "handleTakeItemEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;getItem()Lnet/minecraft/world/item/ItemStack;")) - private void skyblocker$onItemPickup(ClientboundTakeItemEntityPacket packet, CallbackInfo ci, @Local ItemEntity itemEntity) { + private void skyblocker$onItemPickup(ClientboundTakeItemEntityPacket packet, CallbackInfo ci, @Local(name = "itemEntity") ItemEntity itemEntity) { DungeonManager.onItemPickup(itemEntity); } @@ -122,7 +122,7 @@ protected ClientPacketListenerMixin(Minecraft client, Connection connection, Com } @ModifyExpressionValue(method = "handleEntityEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/game/ClientboundEntityEventPacket;getEntity(Lnet/minecraft/world/level/Level;)Lnet/minecraft/world/entity/Entity;")) - private Entity skyblocker$onEntityDeath(Entity entity, @Local(argsOnly = true) ClientboundEntityEventPacket packet) { + private Entity skyblocker$onEntityDeath(Entity entity, @Local(name = "packet") ClientboundEntityEventPacket packet) { if (packet.getEventId() == EntityEvent.DEATH) { DungeonScore.handleEntityDeath(entity); TheEnd.onEntityDeath(entity); diff --git a/src/main/java/de/hysky/skyblocker/mixins/ContainerScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ContainerScreenMixin.java index c49468c866..ba5da77dfb 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ContainerScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ContainerScreenMixin.java @@ -1,34 +1,58 @@ package de.hysky.skyblocker.mixins; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.museum.MuseumManager; +import de.hysky.skyblocker.utils.Utils; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.ChestMenu; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; @Mixin(ContainerScreen.class) public abstract class ContainerScreenMixin extends AbstractContainerScreen { - public ContainerScreenMixin(ChestMenu handler, Inventory inventory, Component title) { super(handler, inventory, title); } - @ModifyVariable( - method = "renderBg", - at = @At("STORE"), - index = 5) + @SuppressWarnings("unused") + @Override + protected void init() { + super.init(); + + // Museum Overlay + if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.museumOverlay && this.minecraft.player != null && this.getTitle().getString().contains("Museum")) { + int overlayWidth = MuseumManager.BACKGROUND_WIDTH; // width of the overlay + int spacing = MuseumManager.SPACING; // space between inventory and overlay + + // Default: center inventory + int inventoryX = (this.width - this.imageWidth) / 2; + + // If overlay would go off the right edge, shift inventory left + if (inventoryX + this.imageWidth + spacing + overlayWidth > this.width) { + inventoryX = this.width - (this.imageWidth + overlayWidth + spacing); + if (inventoryX < 0) inventoryX = 0; + } + this.leftPos = inventoryX; + + new MuseumManager(this, this.leftPos, this.topPos, this.imageWidth); + } + } + + // The following two mixins are needed for the Accessory Helper & Museum Overlay + + @ModifyVariable(method = "extractBackground", at = @At("STORE"), name = "xo") public int x(int ignored) { - return leftPos; + return this.leftPos; } - @ModifyVariable( - method = "renderBg", - at = @At("STORE"), - index = 6) + @ModifyVariable(method = "extractBackground", at = @At("STORE"), name = "yo") public int y(int ignored) { - return topPos; + return this.topPos; } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/DyedItemColorMixin.java b/src/main/java/de/hysky/skyblocker/mixins/DyedItemColorMixin.java index ef383edc57..aa3b95f5d4 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/DyedItemColorMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/DyedItemColorMixin.java @@ -15,7 +15,7 @@ public class DyedItemColorMixin { @ModifyReturnValue(method = "getOrDefault", at = @At("RETURN")) - private static int skyblocker$customDyeColor(int originalColor, @Local(argsOnly = true) ItemStack stack) { + private static int skyblocker$customDyeColor(int originalColor, @Local(name = "itemStack") ItemStack stack) { if (Utils.isOnSkyblock()) { String itemUuid = stack.getUuid(); diff --git a/src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java b/src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java index f13f73057a..0fa5ba42f4 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java @@ -18,7 +18,7 @@ public class EntityRenderDispatcherMixin { @ModifyReturnValue(method = "shouldRender", at = @At("RETURN")) - private boolean skyblocker$shouldRender(boolean original, @Local(argsOnly = true) E entity) { + private boolean skyblocker$shouldRender(boolean original, @Local(name = "entity") E entity) { // Don't render Sven Pup's Nametag if ((Utils.isInHub() || Utils.isInPark()) && SkyblockerConfigManager.get().slayers.wolfSlayer.hideSvenPupNametag && entity instanceof ArmorStand armorStand && armorStand.getCustomName() instanceof Component nameTag && nameTag.getString().contains("Sven Pup")) return false; diff --git a/src/main/java/de/hysky/skyblocker/mixins/EntityRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/EntityRendererMixin.java index 08eb7f6cc7..2624cf260f 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/EntityRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/EntityRendererMixin.java @@ -25,7 +25,7 @@ public class EntityRendererMixin { @Inject(method = "extractRenderState", at = @At("TAIL")) - private void skyblocker$customGlow(CallbackInfo ci, @Local(argsOnly = true) Entity entity, @Local(argsOnly = true) EntityRenderState state) { + private void skyblocker$customGlow(CallbackInfo ci, @Local(name = "entity") Entity entity, @Local(name = "state") EntityRenderState state) { boolean allowGlowInLivid = LividColor.allowGlow(); boolean customGlow = MobGlow.hasOrComputeMobGlow(entity); boolean allowGlow = allowGlowInLivid && state.appearsGlowing() || customGlow; @@ -45,15 +45,15 @@ public class EntityRendererMixin { // This is meant to be separate from the previous injection for organizational purposes. @Inject(method = "extractRenderState", at = @At(value = "TAIL")) - private void skyblocker$mobBoundingBox(CallbackInfo ci, @Local(argsOnly = true) Entity entity, @Local(argsOnly = true) float partialTick) { + private void skyblocker$mobBoundingBox(CallbackInfo ci, @Local(name = "entity") Entity entity, @Local(name = "partialTicks") float partialTicks) { if (MobBoundingBoxes.shouldDrawMobBoundingBox(entity)) { - MobBoundingBoxes.submitBox2BeRendered(Boxes.lerpEntityBoundingBox(entity, partialTick), MobBoundingBoxes.getBoxColor(entity)); + MobBoundingBoxes.submitBox2BeRendered(Boxes.lerpEntityBoundingBox(entity, partialTicks), MobBoundingBoxes.getBoxColor(entity)); return; } if (SlayerManager.shouldGlow(entity, SlayersConfig.HighlightSlayerEntities.HITBOX)) { float[] color = ColorUtils.getFloatComponents(SkyblockerConfigManager.get().slayers.highlightColor.getRGB()); - MobBoundingBoxes.submitBox2BeRendered(Boxes.lerpEntityBoundingBox(entity, partialTick), color); + MobBoundingBoxes.submitBox2BeRendered(Boxes.lerpEntityBoundingBox(entity, partialTicks), color); } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/EquipmentLayerRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/EquipmentLayerRendererMixin.java index fb34cd7f24..6d56c687e1 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/EquipmentLayerRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/EquipmentLayerRendererMixin.java @@ -19,7 +19,7 @@ public class EquipmentLayerRendererMixin { @ModifyVariable(method = "renderLayers(Lnet/minecraft/client/resources/model/EquipmentClientInfo$LayerType;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/client/model/Model;Ljava/lang/Object;Lnet/minecraft/world/item/ItemStack;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/resources/Identifier;II)V", at = @At("HEAD"), argsOnly = true) - private ResourceKey customArmorModel(ResourceKey assetKey, @Local(argsOnly = true) ItemStack stack) { + private ResourceKey customArmorModel(ResourceKey assetKey, @Local(name = "itemStack") ItemStack stack) { if (Utils.isOnSkyblock() && !stack.getUuid().isEmpty()) { Identifier identifier = SkyblockerConfigManager.get().general.customArmorModel.get(stack.getUuid()); return identifier == null ? assetKey : ResourceKey.create(EquipmentAssets.ROOT_ID, identifier); diff --git a/src/main/java/de/hysky/skyblocker/mixins/FogRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/FogRendererMixin.java index 1e867fb5b8..28944c0f32 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/FogRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/FogRendererMixin.java @@ -20,13 +20,13 @@ public class FogRendererMixin { * Moves fog farther away from the player when in the crimson isles. * This sets it to be the same distance as what you would see in the overworld (every other skyblock island) */ - @Inject(method = "setupFog(Lnet/minecraft/client/Camera;ILnet/minecraft/client/DeltaTracker;FLnet/minecraft/client/multiplayer/ClientLevel;)Lorg/joml/Vector4f;", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/fog/FogData;renderDistanceEnd:F", opcode = Opcodes.PUTFIELD, shift = At.Shift.AFTER)) - private void applyFogModifyDistance(CallbackInfoReturnable ci, @Local FogData fogData) { + @Inject(method = "setupFog(Lnet/minecraft/client/Camera;ILnet/minecraft/client/DeltaTracker;FLnet/minecraft/client/multiplayer/ClientLevel;)Lnet/minecraft/client/renderer/fog/FogData;", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/fog/FogData;renderDistanceEnd:F", opcode = Opcodes.PUTFIELD, shift = At.Shift.AFTER)) + private void applyFogModifyDistance(CallbackInfoReturnable ci, @Local(name = "fog") FogData fog) { if (Utils.isOnSkyblock() && Utils.isInCrimson() && SkyblockerConfigManager.get().crimsonIsle.extendNetherFog) { - fogData.environmentalStart = Float.MAX_VALUE; - fogData.environmentalEnd = Float.MAX_VALUE; - fogData.renderDistanceStart = Float.MAX_VALUE; - fogData.renderDistanceEnd = Float.MAX_VALUE; + fog.environmentalStart = Float.MAX_VALUE; + fog.environmentalEnd = Float.MAX_VALUE; + fog.renderDistanceStart = Float.MAX_VALUE; + fog.renderDistanceEnd = Float.MAX_VALUE; } } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/GameRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/GameRendererMixin.java index 371fb0eb0d..2d197581bf 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/GameRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/GameRendererMixin.java @@ -5,7 +5,7 @@ import de.hysky.skyblocker.skyblock.dungeon.DungeonMapTexture; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.GlowRenderer; -import de.hysky.skyblocker.utils.render.HudHelper; +import de.hysky.skyblocker.utils.render.GuiHelper; import de.hysky.skyblocker.utils.render.Renderer; import net.minecraft.client.renderer.GameRenderer; import org.spongepowered.asm.mixin.Mixin; @@ -20,7 +20,7 @@ public class GameRendererMixin { private void skyblocker$onGameRendererClose(CallbackInfo ci) { Renderer.close(); GlowRenderer.getInstance().close(); - HudHelper.close(); + GuiHelper.close(); DungeonMapTexture.close(); } @@ -33,4 +33,9 @@ private static float onGetNightVisionStrength(float original) { } return original; } + + @Inject(method = "render", at = @At(value = "CONSTANT", args = "stringValue=gui")) + private void skyblocker$onRenderGui(CallbackInfo ci) { + GuiHelper.updateScreenBlitTexture(); + } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/GlCommandEncoderMixin.java b/src/main/java/de/hysky/skyblocker/mixins/GlCommandEncoderMixin.java index cace5f8fe2..8d8f5d3717 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/GlCommandEncoderMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/GlCommandEncoderMixin.java @@ -9,16 +9,15 @@ import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.buffers.GpuBufferSlice; import com.mojang.blaze3d.opengl.DirectStateAccess; -import com.mojang.blaze3d.opengl.GlCommandEncoder; import de.hysky.skyblocker.mixins.accessors.DirectStateAccessInvoker; -@Mixin(GlCommandEncoder.class) +@Mixin(targets = "com.mojang.blaze3d.opengl.GlCommandEncoder") public class GlCommandEncoderMixin { @WrapWithCondition(method = "writeToBuffer", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/opengl/DirectStateAccess;bufferSubData(IJLjava/nio/ByteBuffer;I)V")) - private static boolean skyblocker$replaceBufferData(DirectStateAccess manager, int buffer, long offset, ByteBuffer data, int usage, @Local(argsOnly = true) GpuBufferSlice gpuBufferSlice) { - if (offset == 0 && gpuBufferSlice.length() == gpuBufferSlice.buffer().size()) { - ((DirectStateAccessInvoker) manager).invokeBufferData(buffer, data, gpuBufferSlice.buffer().usage()); + private static boolean skyblocker$replaceBufferData(DirectStateAccess manager, int buffer, long offset, ByteBuffer data, int usage, @Local(name = "slice") GpuBufferSlice slice) { + if (offset == 0 && slice.length() == slice.buffer().size()) { + ((DirectStateAccessInvoker) manager).invokeBufferData(buffer, data, slice.buffer().usage()); return false; } diff --git a/src/main/java/de/hysky/skyblocker/mixins/GuiGraphicsMixin.java b/src/main/java/de/hysky/skyblocker/mixins/GuiGraphicsExtractorMixin.java similarity index 61% rename from src/main/java/de/hysky/skyblocker/mixins/GuiGraphicsMixin.java rename to src/main/java/de/hysky/skyblocker/mixins/GuiGraphicsExtractorMixin.java index 93fa4105d9..28c8c79049 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/GuiGraphicsMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/GuiGraphicsExtractorMixin.java @@ -4,15 +4,15 @@ import com.llamalad7.mixinextras.sugar.Local; import de.hysky.skyblocker.skyblock.item.ItemCooldowns; import de.hysky.skyblocker.utils.Utils; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -@Mixin(GuiGraphics.class) -public abstract class GuiGraphicsMixin { - @ModifyExpressionValue(method = "renderItemCooldown", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemCooldowns;getCooldownPercent(Lnet/minecraft/world/item/ItemStack;F)F")) - private float skyblocker$modifyItemCooldown(float cooldownProgress, @Local(argsOnly = true) ItemStack stack) { +@Mixin(GuiGraphicsExtractor.class) +public abstract class GuiGraphicsExtractorMixin { + @ModifyExpressionValue(method = "itemCooldown", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemCooldowns;getCooldownPercent(Lnet/minecraft/world/item/ItemStack;F)F")) + private float skyblocker$modifyItemCooldown(float cooldownProgress, @Local(name = "itemStack") ItemStack stack) { return Utils.isOnSkyblock() && ItemCooldowns.isOnCooldown(stack) ? ItemCooldowns.getItemCooldownEntry(stack).getRemainingCooldownPercent() : cooldownProgress; } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/GuiMixin.java b/src/main/java/de/hysky/skyblocker/mixins/GuiMixin.java index 5c38356309..f2955bb8dc 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/GuiMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/GuiMixin.java @@ -17,7 +17,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; @@ -50,19 +50,19 @@ public abstract class GuiMixin { @Unique private boolean isQuiverSlot = false; - @Inject(method = "renderItemHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/Gui;renderSlot(Lnet/minecraft/client/gui/GuiGraphics;IILnet/minecraft/client/DeltaTracker;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/item/ItemStack;I)V", ordinal = 0)) - public void skyblocker$renderHotbarItemLockOrBackground(CallbackInfo ci, @Local(argsOnly = true) GuiGraphics context, @Local(ordinal = 4, name = "m") int index, @Local(ordinal = 5, name = "n") int x, @Local(ordinal = 6, name = "o") int y, @Local Player player) { + @Inject(method = "extractItemHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/Gui;extractSlot(Lnet/minecraft/client/gui/GuiGraphicsExtractor;IILnet/minecraft/client/DeltaTracker;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/item/ItemStack;I)V", ordinal = 0)) + public void skyblocker$extractHotbarItemLockOrBackground(CallbackInfo ci, @Local(name = "graphics") GuiGraphicsExtractor graphics, @Local(name = "i") int index, @Local(name = "x") int x, @Local(name = "y") int y, @Local(name = "player") Player player) { if (Utils.isOnSkyblock()) { - ItemBackgroundManager.drawBackgrounds(player.getInventory().getNonEquipmentItems().get(index), context, x, y); + ItemBackgroundManager.drawBackgrounds(player.getInventory().getNonEquipmentItems().get(index), graphics, x, y); // slot lock if (HotbarSlotLock.isLocked(index)) { - context.blit(RenderPipelines.GUI_TEXTURED, SLOT_LOCK_ICON.get(), x, y, 0, 0, 16, 16, 16, 16); + graphics.blit(RenderPipelines.GUI_TEXTURED, SLOT_LOCK_ICON.get(), x, y, 0, 0, 16, 16, 16, 16); } //item protection if (ItemProtection.isItemProtected(player.getInventory().getNonEquipmentItems().get(index))) { - context.blit(RenderPipelines.GUI_TEXTURED, ItemProtection.ITEM_PROTECTION_TEX, x, y, 0, 0, 16, 16, 16, 16); + graphics.blit(RenderPipelines.GUI_TEXTURED, ItemProtection.ITEM_PROTECTION_TEX, x, y, 0, 0, 16, 16, 16, 16); } isQuiverSlot = index == 8; } @@ -88,34 +88,34 @@ private static boolean isQuiverItem(ItemStack stack) { return prevQuiverSlot; } - @WrapOperation(method = "renderSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphics;renderItemDecorations(Lnet/minecraft/client/gui/Font;Lnet/minecraft/world/item/ItemStack;II)V")) - private void skyblocker$drawQuiverAmount(GuiGraphics instance, Font textRenderer, ItemStack stack, int x, int y, Operation original) { + @WrapOperation(method = "extractSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;itemDecorations(Lnet/minecraft/client/gui/Font;Lnet/minecraft/world/item/ItemStack;II)V")) + private void skyblocker$extractQuiverAmount(GuiGraphicsExtractor graphics, Font textRenderer, ItemStack stack, int x, int y, Operation original) { if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.trueQuiverCount && isQuiverSlot && isQuiverItem(stack)) { String arrow = ItemUtils.getLoreLineIf(stack, s -> s.trim().startsWith("Active Arrow")); if (arrow == null) { - original.call(instance, textRenderer, stack, x, y); + original.call(graphics, textRenderer, stack, x, y); return; } int i = arrow.lastIndexOf('('); int j = arrow.lastIndexOf(')'); if (i == -1 || j == -1 || i > j) { - original.call(instance, textRenderer, stack, x, y); + original.call(graphics, textRenderer, stack, x, y); return; } arrow = arrow.substring(i + 1, j); OptionalInt anInt = Utils.parseInt(arrow); if (anInt.isEmpty()) { - original.call(instance, textRenderer, stack, x, y); + original.call(graphics, textRenderer, stack, x, y); return; } String format = Formatters.SHORT_INTEGER_NUMBERS.format(anInt.getAsInt()); - instance.renderItemDecorations(textRenderer, stack, x, y, format); + graphics.itemDecorations(textRenderer, stack, x, y, format); } else { - original.call(instance, textRenderer, stack, x, y); + original.call(graphics, textRenderer, stack, x, y); } } - @ModifyExpressionValue(method = "renderCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;getAttackStrengthScale(F)F")) + @ModifyExpressionValue(method = "extractCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;getAttackStrengthScale(F)F")) private float skyblocker$modifyAttackIndicatorCooldown(float cooldownProgress) { if (Utils.isOnSkyblock() && minecraft.player != null) { ItemStack stack = minecraft.player.getMainHandItem(); diff --git a/src/main/java/de/hysky/skyblocker/mixins/InventoryScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/InventoryScreenMixin.java index f6592c3442..20be3279ac 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/InventoryScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/InventoryScreenMixin.java @@ -4,6 +4,7 @@ import de.hysky.skyblocker.compatibility.ResourcePackCompatibility; import de.hysky.skyblocker.injected.RecipeBookHolder; import de.hysky.skyblocker.mixins.accessors.ScreenAccessor; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; @@ -20,7 +21,8 @@ import java.util.ArrayList; import java.util.List; -import net.minecraft.client.gui.GuiGraphics; + +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.EffectsInInventory; import net.minecraft.client.gui.screens.inventory.InventoryScreen; @@ -32,7 +34,6 @@ @Mixin(InventoryScreen.class) public abstract class InventoryScreenMixin extends AbstractContainerScreen implements RecipeBookHolder { - @Unique private final List recipeBookToggleCallbacks = new ArrayList<>(); @@ -42,7 +43,7 @@ public InventoryScreenMixin(InventoryMenu handler, Inventory inventory, Componen @ModifyArg(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractRecipeBookScreen;(Lnet/minecraft/world/inventory/RecipeBookMenu;Lnet/minecraft/client/gui/screens/recipebook/RecipeBookComponent;Lnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/network/chat/Component;)V")) - private static RecipeBookComponent skyblocker$replaceRecipeBook(RecipeBookComponent original, @Local(argsOnly = true) Player player) { + private static RecipeBookComponent skyblocker$replaceRecipeBook(RecipeBookComponent original, @Local(name = "player") Player player) { return SkyblockerConfigManager.get().general.itemList.enableItemList && Utils.isOnSkyblock() ? new SkyblockRecipeBookWidget(player.inventoryMenu) : original; } @@ -51,8 +52,8 @@ public InventoryScreenMixin(InventoryMenu handler, Inventory inventory, Componen return Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.showEquipmentInInventory ? x + 21 : x; } - @WrapWithCondition(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/EffectsInInventory;render(Lnet/minecraft/client/gui/GuiGraphics;II)V")) - private boolean skyblocker$dontDrawStatusEffects(EffectsInInventory statusEffectsDisplay, GuiGraphics context, int mouseX, int mouseY) { + @WrapWithCondition(method = "extractRenderState(Lnet/minecraft/client/gui/GuiGraphicsExtractor;IIF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/EffectsInInventory;extractRenderState(Lnet/minecraft/client/gui/GuiGraphicsExtractor;II)V")) + private boolean skyblocker$dontExtractStatusEffects(EffectsInInventory statusEffectsDisplay, GuiGraphicsExtractor graphics, int mouseX, int mouseY) { return !(Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.hideStatusEffectOverlay || Utils.isInGarden() && SkyblockerConfigManager.get().farming.plotsWidget.enabled); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/ItemFeatureRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ItemFeatureRendererMixin.java index 235c3ccd3d..5c9a0ca02b 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ItemFeatureRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ItemFeatureRendererMixin.java @@ -17,13 +17,13 @@ @Mixin(ItemFeatureRenderer.class) public class ItemFeatureRendererMixin { - @WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeStorage$ItemSubmit;outlineColor()I"), require = 2) - private int skyblocker$useCustomGlowColour(SubmitNodeStorage.ItemSubmit command, Operation operation) { - return command.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? command.skyblocker$getCustomGlowColour() : operation.call(command); + @WrapOperation(method = "renderItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeStorage$ItemSubmit;outlineColor()I"), require = 3) + private int skyblocker$useCustomGlowColour(SubmitNodeStorage.ItemSubmit submit, Operation operation) { + return submit.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? submit.skyblocker$getCustomGlowColour() : operation.call(submit); } - @ModifyVariable(method = "render", at = @At("LOAD"), argsOnly = true, require = 2) - private OutlineBufferSource skyblocker$useCustomGlowConsumers(OutlineBufferSource original, @Local SubmitNodeStorage.ItemSubmit command) { - return command.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? GlowRenderer.getInstance().getGlowVertexConsumers() : original; + @ModifyVariable(method = "renderItem", at = @At("LOAD"), name = "outlineBufferSource", require = 2) + private OutlineBufferSource skyblocker$useCustomGlowConsumers(OutlineBufferSource original, @Local(name = "submit") SubmitNodeStorage.ItemSubmit submit) { + return submit.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? GlowRenderer.getInstance().getGlowBufferSource() : original; } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/ItemStackMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ItemStackMixin.java index 134cdf9f81..d4d63f770f 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ItemStackMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ItemStackMixin.java @@ -74,7 +74,7 @@ public abstract class ItemStackMixin implements DataComponentHolder, SkyblockerS } @ModifyExpressionValue(method = "addToTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/TooltipDisplay;shows(Lnet/minecraft/core/component/DataComponentType;)Z")) - private boolean skyblocker$hideVanillaEnchants(boolean shouldDisplay, @Local TooltipProvider component) { + private boolean skyblocker$hideVanillaEnchants(boolean shouldDisplay, @Local(name = "component") TooltipProvider component) { return shouldDisplay && !(Utils.isOnSkyblock() && component instanceof ItemEnchantments); } @@ -82,7 +82,7 @@ public abstract class ItemStackMixin implements DataComponentHolder, SkyblockerS slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/core/DefaultedRegistry;getKey(Ljava/lang/Object;)Lnet/minecraft/resources/Identifier;")), at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V", shift = At.Shift.AFTER, ordinal = 0) ) - private void skyblocker$skyblockIdTooltip(CallbackInfo ci, @Local(argsOnly = true) Consumer textConsumer) { + private void skyblocker$skyblockIdTooltip(CallbackInfo ci, @Local(name = "builder") Consumer textConsumer) { if (Utils.isOnSkyblock()) { String skyblockId = getSkyblockId(); @@ -115,7 +115,7 @@ private int modifyItemBarColor(int original) { return durabilityBarFill >= 0 ? OkLabColor.interpolate(CommonColors.RED, CommonColors.GREEN, durabilityBarFill) : original; } - @Inject(method = "(Lnet/minecraft/world/level/ItemLike;ILnet/minecraft/core/component/PatchedDataComponentMap;)V", at = @At("TAIL")) + @Inject(method = "(Lnet/minecraft/core/Holder;ILnet/minecraft/core/component/PatchedDataComponentMap;)V", at = @At("TAIL")) private void onInit(CallbackInfo ci) { skyblocker$getAndCacheDurability(); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/LevelLoadingScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/LevelLoadingScreenMixin.java index 74d5ddac43..a927cfa7f4 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/LevelLoadingScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/LevelLoadingScreenMixin.java @@ -15,7 +15,7 @@ public class LevelLoadingScreenMixin { @Shadow private LevelLoadTracker loadTracker; - @Inject(method = { "render", "renderBackground" }, at = @At("HEAD"), cancellable = true) + @Inject(method = { "extractRenderState", "extractBackground" }, at = @At("HEAD"), cancellable = true, require = 2) private void skyblocker$hideWorldLoadingScreen(CallbackInfo ci) { if (Utils.isOnHypixel() && this.loadTracker.statusView() == null) ci.cancel(); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/LevelRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/LevelRendererMixin.java index dd46607f14..f5f2ed1b80 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/LevelRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/LevelRendererMixin.java @@ -9,12 +9,13 @@ import de.hysky.skyblocker.skyblock.dwarven.BlockBreakPrediction; import de.hysky.skyblocker.skyblock.entity.MobGlow; import de.hysky.skyblocker.utils.render.GlowRenderer; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.entity.state.EntityRenderState; -import net.minecraft.client.renderer.state.BlockBreakingRenderState; -import net.minecraft.client.renderer.state.LevelRenderState; +import net.minecraft.client.renderer.state.level.BlockBreakingRenderState; +import net.minecraft.client.renderer.state.level.LevelRenderState; import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; + import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -39,7 +40,7 @@ public class LevelRendererMixin implements EntityRenderMarker { } @ModifyExpressionValue(method = "extractVisibleEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/state/EntityRenderState;appearsGlowing()Z")) - private boolean skyblocker$markCustomGlowUsedThisFrame(boolean hasVanillaGlow, @Local EntityRenderState entityRenderState) { + private boolean skyblocker$markCustomGlowUsedThisFrame(boolean hasVanillaGlow, @Local(name = "state") EntityRenderState entityRenderState) { boolean hasCustomGlow = entityRenderState.getDataOrDefault(MobGlow.ENTITY_CUSTOM_GLOW_COLOUR, MobGlow.NO_GLOW) != MobGlow.NO_GLOW; if (hasCustomGlow) { @@ -49,7 +50,7 @@ public class LevelRendererMixin implements EntityRenderMarker { return hasVanillaGlow || hasCustomGlow; } - @Inject(method = "method_62214", + @Inject(method = "lambda$addMainPass$0", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;shouldShowEntityOutlines()Z")), at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/CommandEncoder;clearColorAndDepthTextures(Lcom/mojang/blaze3d/textures/GpuTexture;ILcom/mojang/blaze3d/textures/GpuTexture;D)V", ordinal = 0, shift = At.Shift.AFTER) ) @@ -59,32 +60,31 @@ public class LevelRendererMixin implements EntityRenderMarker { } } - @Inject(method = "submitEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;submit(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/renderer/state/CameraRenderState;DDDLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;)V")) - private void skyblocker$markEntityStateBeingRendered(CallbackInfo ci, @Local EntityRenderState state) { + @Inject(method = "submitEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;submit(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/renderer/state/level/CameraRenderState;DDDLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;)V")) + private void skyblocker$markEntityStateBeingRendered(CallbackInfo ci, @Local(name = "state") EntityRenderState state) { this.currentEntityStateBeingRendered = state; } - @Inject(method = "submitEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;submit(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/renderer/state/CameraRenderState;DDDLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;)V", shift = At.Shift.AFTER)) + @Inject(method = "submitEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;submit(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/renderer/state/level/CameraRenderState;DDDLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;)V", shift = At.Shift.AFTER)) private void skyblocker$clearEntityStateBeingRendered(CallbackInfo ci) { this.currentEntityStateBeingRendered = null; } - @Inject(method = "method_62214", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/OutlineBufferSource;endOutlineBatch()V")) + @Inject(method = "lambda$addMainPass$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/OutlineBufferSource;endOutlineBatch()V")) private void skyblocker$drawGlowVertexConsumers(CallbackInfo ci) { - GlowRenderer.getInstance().getGlowVertexConsumers().endOutlineBatch(); + GlowRenderer.getInstance().getGlowBufferSource().endOutlineBatch(); } - @WrapOperation(method = "extractBlockDestroyAnimation", at = @At(value = "NEW", target = "(Lnet/minecraft/client/multiplayer/ClientLevel;Lnet/minecraft/core/BlockPos;I)Lnet/minecraft/client/renderer/state/BlockBreakingRenderState;")) - private BlockBreakingRenderState skyblocker$addBlockBreakingProgressRenderState(ClientLevel clientLevel, BlockPos blockPos, int i, Operation original) { + @WrapOperation(method = "extractBlockDestroyAnimation", at = @At(value = "NEW", target = "(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Lnet/minecraft/client/renderer/state/level/BlockBreakingRenderState;")) + private BlockBreakingRenderState skyblocker$addBlockBreakingProgressRenderState(BlockPos pos, BlockState state, int progress, Operation original) { if (SkyblockerConfigManager.get().mining.blockBreakPrediction.enabled) { - int pingModifiedProgress = BlockBreakPrediction.getBlockBreakPrediction(blockPos, i); - return new BlockBreakingRenderState(clientLevel, blockPos, pingModifiedProgress); + int pingModifiedProgress = BlockBreakPrediction.getBlockBreakPrediction(pos, progress); + return new BlockBreakingRenderState(pos, state, pingModifiedProgress); } //if the setting is not enabled do not modify anything else { - return original.call(clientLevel, blockPos, i); + return original.call(pos, state, progress); } - } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/MapRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/MapRendererMixin.java index c17e920890..1307147e44 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/MapRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/MapRendererMixin.java @@ -14,7 +14,7 @@ @Mixin(MapRenderer.class) public class MapRendererMixin { @ModifyExpressionValue(method = "extractDecorationRenderState", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/saveddata/maps/MapDecoration;renderOnFrame()Z")) - private boolean preventDecorationInDungeons(boolean alwaysRendered, @Local(argsOnly = true) MapDecoration decoration) { + private boolean preventDecorationInDungeons(boolean alwaysRendered, @Local(name = "decoration") MapDecoration decoration) { // Allow alwaysRendered if // 1. not in dungeons and map is disabled OR // 2. the decoration type is frame (self player) and either fancy map or show self head are off OR diff --git a/src/main/java/de/hysky/skyblocker/mixins/MenuScreensConstructorMixin.java b/src/main/java/de/hysky/skyblocker/mixins/MenuScreensConstructorMixin.java index 68521f0961..403f3bd9bc 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/MenuScreensConstructorMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/MenuScreensConstructorMixin.java @@ -40,8 +40,8 @@ public interface MenuScreensConstructorMixin { switch (screenHandler) { // Better party finder - case ChestMenu ignored when SkyblockerConfigManager.get().dungeons.fancyPartyFinder && nameLowercase.startsWith("select tier") -> PartyFinderScreen.isInKuudraPartyFinder = true; - case ChestMenu ignored when SkyblockerConfigManager.get().dungeons.fancyPartyFinder && nameLowercase.startsWith("catacombs") -> PartyFinderScreen.isInKuudraPartyFinder = false; + case ChestMenu _ when SkyblockerConfigManager.get().dungeons.fancyPartyFinder && nameLowercase.startsWith("select tier") -> PartyFinderScreen.isInKuudraPartyFinder = true; + case ChestMenu _ when SkyblockerConfigManager.get().dungeons.fancyPartyFinder && nameLowercase.startsWith("catacombs") -> PartyFinderScreen.isInKuudraPartyFinder = false; case ChestMenu containerScreenHandler when SkyblockerConfigManager.get().dungeons.fancyPartyFinder && PartyFinderScreen.possibleInventoryNames.contains(nameLowercase) -> { if (client.screen != null) { diff --git a/src/main/java/de/hysky/skyblocker/mixins/ModelFeatureRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ModelFeatureRendererMixin.java index fcb8eb5ce4..bfdef67886 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ModelFeatureRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ModelFeatureRendererMixin.java @@ -18,12 +18,12 @@ public class ModelFeatureRendererMixin { @WrapOperation(method = "renderModel(Lnet/minecraft/client/renderer/SubmitNodeStorage$ModelSubmit;Lnet/minecraft/client/renderer/rendertype/RenderType;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/client/renderer/OutlineBufferSource;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeStorage$ModelSubmit;outlineColor()I"), require = 2) - private int skyblocker$useCustomGlowColour(SubmitNodeStorage.ModelSubmit command, Operation operation) { - return command.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? command.skyblocker$getCustomGlowColour() : operation.call(command); + private int skyblocker$useCustomGlowColour(SubmitNodeStorage.ModelSubmit submit, Operation operation) { + return submit.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? submit.skyblocker$getCustomGlowColour() : operation.call(submit); } - @ModifyVariable(method = "renderModel(Lnet/minecraft/client/renderer/SubmitNodeStorage$ModelSubmit;Lnet/minecraft/client/renderer/rendertype/RenderType;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/client/renderer/OutlineBufferSource;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;)V", at = @At("LOAD"), argsOnly = true, require = 2) - private OutlineBufferSource skyblocker$useCustomGlowConsumers(OutlineBufferSource original, @Local(argsOnly = true) SubmitNodeStorage.ModelSubmit command) { - return command.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? GlowRenderer.getInstance().getGlowVertexConsumers() : original; + @ModifyVariable(method = "renderModel(Lnet/minecraft/client/renderer/SubmitNodeStorage$ModelSubmit;Lnet/minecraft/client/renderer/rendertype/RenderType;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/client/renderer/OutlineBufferSource;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;)V", at = @At("LOAD"), name = "outlineBufferSource", require = 2) + private OutlineBufferSource skyblocker$useCustomGlowConsumers(OutlineBufferSource original, @Local(name = "submit") SubmitNodeStorage.ModelSubmit submit) { + return submit.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? GlowRenderer.getInstance().getGlowBufferSource() : original; } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/ModelPartFeatureRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ModelPartFeatureRendererMixin.java index 6e678f2398..1aed79d1d4 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ModelPartFeatureRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ModelPartFeatureRendererMixin.java @@ -22,8 +22,8 @@ public class ModelPartFeatureRendererMixin { return command.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? command.skyblocker$getCustomGlowColour() : operation.call(command); } - @ModifyVariable(method = "render", at = @At("LOAD"), argsOnly = true, require = 2) - private OutlineBufferSource skyblocker$useCustomGlowConsumers(OutlineBufferSource original, @Local SubmitNodeStorage.ModelPartSubmit command) { - return command.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? GlowRenderer.getInstance().getGlowVertexConsumers() : original; + @ModifyVariable(method = "render", at = @At("LOAD"), name = "outlineBufferSource", require = 2) + private OutlineBufferSource skyblocker$useCustomGlowConsumers(OutlineBufferSource original, @Local(name = "modelPartSubmit") SubmitNodeStorage.ModelPartSubmit submit) { + return submit.skyblocker$getCustomGlowColour() != MobGlow.NO_GLOW ? GlowRenderer.getInstance().getGlowBufferSource() : original; } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/MultiPlayerGameModeMixin.java b/src/main/java/de/hysky/skyblocker/mixins/MultiPlayerGameModeMixin.java index 0b81a1b1b1..703bb27d2c 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/MultiPlayerGameModeMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/MultiPlayerGameModeMixin.java @@ -21,12 +21,12 @@ public class MultiPlayerGameModeMixin { // Inject so that we only swing when the result is not success because vanilla handles swing on success. @Dynamic("Lambda inside of useItem") - @Inject(method = "method_41929", + @Inject(method = "lambda$useItem$0", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;use(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResult;")), at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/entity/player/Player;getItemInHand(Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/item/ItemStack;") ) public void swingOnAbility(InteractionHand hand, Player playerEntity, MutableObject mutableObject, - int sequence, CallbackInfoReturnable> cir, @Local(ordinal = 0) ItemStack itemStack) { + int sequence, CallbackInfoReturnable> cir, @Local(name = "itemStack") ItemStack itemStack) { if (SkyblockerConfigManager.get().uiAndVisuals.swingOnAbilities && SwingAnimation.hasAbility(itemStack)) { swingHandWithoutPackets(playerEntity, hand); diff --git a/src/main/java/de/hysky/skyblocker/mixins/PlayerTabOverlayMixin.java b/src/main/java/de/hysky/skyblocker/mixins/PlayerTabOverlayMixin.java index 1eaa0c842c..71331fabc6 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/PlayerTabOverlayMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/PlayerTabOverlayMixin.java @@ -11,7 +11,7 @@ @Mixin(PlayerTabOverlay.class) public class PlayerTabOverlayMixin { - @Inject(method = "renderPingIcon", at = @At("HEAD"), cancellable = true) + @Inject(method = "extractPingIcon", at = @At("HEAD"), cancellable = true) private void skyblocker$hideLatencyIcon(CallbackInfo ci) { if (Utils.isOnSkyblock()) ci.cancel(); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/QuickNavMixin.java b/src/main/java/de/hysky/skyblocker/mixins/QuickNavMixin.java new file mode 100644 index 0000000000..23c566bc8f --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixins/QuickNavMixin.java @@ -0,0 +1,61 @@ +package de.hysky.skyblocker.mixins; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.quicknav.QuickNav; +import de.hysky.skyblocker.skyblock.quicknav.QuickNavButton; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import org.jspecify.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(AbstractContainerScreen.class) +public abstract class QuickNavMixin extends QuickNavScreenMixin { + @Unique + private @Nullable List quickNavButtons; + + @Inject(method = "init()V", at = @At(value = "TAIL")) + protected void skyblocker$initQuickNav(CallbackInfo ci) { + Screen instance = (Screen) (Object) this; + if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().quickNav.enableQuickNav && Minecraft.getInstance().player != null && !Minecraft.getInstance().player.isCreative()) { + for (QuickNavButton quickNavButton : this.quickNavButtons = QuickNav.init(instance.getTitle().getString().trim())) { + instance.addWidget(quickNavButton); + } + } + } + + /** + * Draws the unselected tabs in front of the background, but behind the main inventory, similar to creative inventory tabs. + */ + @Override + protected void skyblocker$extractUnselectedQuickNavButtons(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a, CallbackInfo ci) { + if (this.quickNavButtons != null) for (QuickNavButton quickNavButton : this.quickNavButtons) { + // Render the button behind the main inventory background if it's not toggled or if it's still fading in + if (!quickNavButton.toggled() || quickNavButton.getAlpha() < 255) { + quickNavButton.setRenderInFront(false); + quickNavButton.extractRenderState(graphics, mouseX, mouseY, a); + } + } + } + + /** + * Draws the selected tab in front of the background and the main inventory, similar to creative inventory tabs. + */ + @Override + protected void skyblocker$extractSelectedQuickNavButtons(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a, CallbackInfo ci) { + if (this.quickNavButtons != null) for (QuickNavButton quickNavButton : this.quickNavButtons) { + if (quickNavButton.toggled()) { + quickNavButton.setRenderInFront(true); + quickNavButton.extractRenderState(graphics, mouseX, mouseY, a); + } + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixins/QuickNavScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/QuickNavScreenMixin.java new file mode 100644 index 0000000000..edbd03f499 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixins/QuickNavScreenMixin.java @@ -0,0 +1,17 @@ +package de.hysky.skyblocker.mixins; + +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.screens.Screen; +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(Screen.class) +public abstract class QuickNavScreenMixin { + @Inject(method = "extractBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;extractTransparentBackground(Lnet/minecraft/client/gui/GuiGraphicsExtractor;)V", shift = At.Shift.AFTER)) + protected void skyblocker$extractUnselectedQuickNavButtons(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a, CallbackInfo ci) {} + + @Inject(method = "extractRenderStateWithTooltipAndSubtitles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;extractBackground(Lnet/minecraft/client/gui/GuiGraphicsExtractor;IIF)V", shift = At.Shift.AFTER)) + protected void skyblocker$extractSelectedQuickNavButtons(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a, CallbackInfo ci) {} +} diff --git a/src/main/java/de/hysky/skyblocker/mixins/RenderFishMixin.java b/src/main/java/de/hysky/skyblocker/mixins/RenderFishMixin.java index e5ef2582b4..dd3972dc0f 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/RenderFishMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/RenderFishMixin.java @@ -15,7 +15,7 @@ public abstract class RenderFishMixin { @ModifyReturnValue(method = "shouldRender", at = @At("RETURN")) - private boolean skyblocker$render(boolean original, @Local(argsOnly = true) FishingHook fishingBobberEntity) { + private boolean skyblocker$render(boolean original, @Local(name = "entity") FishingHook fishingBobberEntity) { //if rendered bobber is not the players and option to hide others is enabled do not render the bobber return Utils.isOnSkyblock() && SkyblockerConfigManager.get().helpers.fishing.hideOtherPlayersRods ? original && Objects.equals(Minecraft.getInstance().player, fishingBobberEntity.getPlayerOwner()) diff --git a/src/main/java/de/hysky/skyblocker/mixins/RenderPipelineMixin.java b/src/main/java/de/hysky/skyblocker/mixins/RenderPipelineMixin.java index a56ae5ab17..f8066d20ed 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/RenderPipelineMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/RenderPipelineMixin.java @@ -4,8 +4,8 @@ import org.spongepowered.asm.mixin.injection.At; import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.mojang.blaze3d.pipeline.DepthStencilState; import com.mojang.blaze3d.pipeline.RenderPipeline; -import com.mojang.blaze3d.platform.DepthTestFunction; import de.hysky.skyblocker.utils.render.GlowRenderer; import net.minecraft.client.renderer.RenderPipelines; @@ -13,8 +13,8 @@ @Mixin(RenderPipeline.class) public class RenderPipelineMixin { - @ModifyReturnValue(method = "getDepthTestFunction", at = @At("RETURN")) - private DepthTestFunction skyblocker$modifyGlowDepthTest(DepthTestFunction original) { - return ((Object) this == RenderPipelines.OUTLINE_CULL || (Object) this == RenderPipelines.OUTLINE_NO_CULL) && GlowRenderer.isRenderingGlow() ? DepthTestFunction.LEQUAL_DEPTH_TEST : original; + @ModifyReturnValue(method = "getDepthStencilState", at = @At("RETURN")) + private DepthStencilState skyblocker$modifyGlowDepthTest(DepthStencilState original) { + return ((Object) this == RenderPipelines.OUTLINE_CULL || (Object) this == RenderPipelines.OUTLINE_NO_CULL) && GlowRenderer.isRenderingGlow() ? DepthStencilState.DEFAULT : original; } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/ScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ScreenMixin.java index 530f9c7a31..3838f5bf4c 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ScreenMixin.java @@ -42,7 +42,7 @@ public class ScreenMixin { } } - @Inject(method = "render", at = @At("HEAD"), cancellable = true) + @Inject(method = "extractRenderState", at = @At("HEAD"), cancellable = true) private void skyblocker$hideReconfiguringScreen(CallbackInfo ci) { if ((Object) this instanceof ServerReconfigScreen && Utils.isOnHypixel()) ci.cancel(); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/SkinManagerMixin.java b/src/main/java/de/hysky/skyblocker/mixins/SkinManagerMixin.java index e5e000b6de..fecb2bf42b 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/SkinManagerMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/SkinManagerMixin.java @@ -11,7 +11,7 @@ @Mixin(targets = "net.minecraft.client.resources.SkinManager$1") public class SkinManagerMixin { - @WrapWithCondition(method = "method_54647", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V")) + @WrapWithCondition(method = "lambda$load$0", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V")) private static boolean skyblocker$dontLogInvalidSignatureWarnings(Logger logger, String message, Object profileId) { return !Utils.isOnHypixel(); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/SynchedEntityDataMixin.java b/src/main/java/de/hysky/skyblocker/mixins/SynchedEntityDataMixin.java index 7357fef836..b10f63675e 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/SynchedEntityDataMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/SynchedEntityDataMixin.java @@ -31,7 +31,7 @@ public abstract class SynchedEntityDataMixin { @SuppressWarnings("ConstantValue") @Inject(method = "assignValues", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/syncher/SynchedEntityData;assignValue(Lnet/minecraft/network/syncher/SynchedEntityData$DataItem;Lnet/minecraft/network/syncher/SynchedEntityData$DataValue;)V")) - private void skyblocker$onWriteUpdatedEntries(CallbackInfo ci, @Local SynchedEntityData.DataItem entry, @Local SynchedEntityData.DataValue serializedEntry) { + private void skyblocker$onWriteUpdatedEntries(CallbackInfo ci, @Local(name = "dataItem") SynchedEntityData.DataItem entry, @Local(name = "item") SynchedEntityData.DataValue serializedEntry) { if (Utils.isInTheEnd() && SkyblockerConfigManager.get().slayers.endermanSlayer.enableYangGlyphsNotification && entry.getAccessor() == EnderManAccessor.getDATA_CARRY_STATE() && entry.getValue() instanceof Optional value && value.isPresent() && value.get() instanceof BlockState state && state.is(Blocks.BEACON) && ((Optional) serializedEntry.value()).isEmpty()) { Minecraft client = Minecraft.getInstance(); if (entity instanceof Entity entity && MobGlow.getArmorStands(entity).stream().anyMatch(armorStand -> armorStand.getName().getString().contains(client.getUser().getName()))) { diff --git a/src/main/java/de/hysky/skyblocker/mixins/YggdrasilServicesKeyInfoMixin.java b/src/main/java/de/hysky/skyblocker/mixins/YggdrasilServicesKeyInfoMixin.java index 7de5e946c6..1800a433a1 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/YggdrasilServicesKeyInfoMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/YggdrasilServicesKeyInfoMixin.java @@ -35,7 +35,7 @@ public class YggdrasilServicesKeyInfoMixin { } catch (IllegalArgumentException e) { try { return decode.call(decoder, signature.replaceAll("[^A-Za-z0-9+/=]", "")); - } catch (IllegalArgumentException e2) { + } catch (IllegalArgumentException _) { if (Utils.isOnSkyblock()) { if (REPLACEMENT_MAP.containsKey(signature)) { return decode.call(decoder, REPLACEMENT_MAP.get(signature)); diff --git a/src/main/java/de/hysky/skyblocker/mixins/accessors/AbstractContainerScreenAccessor.java b/src/main/java/de/hysky/skyblocker/mixins/accessors/AbstractContainerScreenAccessor.java index efec2ecc91..5537419128 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/accessors/AbstractContainerScreenAccessor.java +++ b/src/main/java/de/hysky/skyblocker/mixins/accessors/AbstractContainerScreenAccessor.java @@ -28,8 +28,8 @@ public interface AbstractContainerScreenAccessor { @Accessor int getImageHeight(); - @Mutable @Accessor("menu") + @Mutable void setHandler(AbstractContainerMenu handler); @Accessor("hoveredSlot") diff --git a/src/main/java/de/hysky/skyblocker/mixins/accessors/BlockEntityRenderStateAccessor.java b/src/main/java/de/hysky/skyblocker/mixins/accessors/BlockEntityRenderStateAccessor.java new file mode 100644 index 0000000000..593a0c4da5 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixins/accessors/BlockEntityRenderStateAccessor.java @@ -0,0 +1,14 @@ +package de.hysky.skyblocker.mixins.accessors; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState; +import net.minecraft.world.level.block.state.BlockState; + +@Mixin(BlockEntityRenderState.class) +public interface BlockEntityRenderStateAccessor { + + @Accessor + void setBlockState(BlockState blockState); +} diff --git a/src/main/java/de/hysky/skyblocker/mixins/accessors/DataComponentPatchAccessor.java b/src/main/java/de/hysky/skyblocker/mixins/accessors/DataComponentPatchAccessor.java new file mode 100644 index 0000000000..dd255a1efa --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixins/accessors/DataComponentPatchAccessor.java @@ -0,0 +1,22 @@ +package de.hysky.skyblocker.mixins.accessors; + +import java.util.Optional; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.component.DataComponentType; + +@Mixin(DataComponentPatch.class) +public interface DataComponentPatchAccessor { + @Accessor + Reference2ObjectMap, Optional> getMap(); + + @Invoker("") + static DataComponentPatch invokeInit(Reference2ObjectMap, Optional> map) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixins/accessors/EditBoxAccessor.java b/src/main/java/de/hysky/skyblocker/mixins/accessors/EditBoxAccessor.java new file mode 100644 index 0000000000..ea8ace730b --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixins/accessors/EditBoxAccessor.java @@ -0,0 +1,19 @@ +package de.hysky.skyblocker.mixins.accessors; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.client.gui.components.EditBox; + +@Mixin(EditBox.class) +public interface EditBoxAccessor { + @Accessor + int getHighlightPos(); + + @Accessor + int getMaxLength(); + + @Invoker + void invokeOnValueChange(String value); +} diff --git a/src/main/java/de/hysky/skyblocker/mixins/accessors/GuiGraphicsInvoker.java b/src/main/java/de/hysky/skyblocker/mixins/accessors/GuiGraphicsExtractorInvoker.java similarity index 51% rename from src/main/java/de/hysky/skyblocker/mixins/accessors/GuiGraphicsInvoker.java rename to src/main/java/de/hysky/skyblocker/mixins/accessors/GuiGraphicsExtractorInvoker.java index 805ecfdd91..9338324b7f 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/accessors/GuiGraphicsInvoker.java +++ b/src/main/java/de/hysky/skyblocker/mixins/accessors/GuiGraphicsExtractorInvoker.java @@ -6,12 +6,12 @@ import com.mojang.blaze3d.pipeline.RenderPipeline; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.render.TextureSetup; -@Mixin(GuiGraphics.class) -public interface GuiGraphicsInvoker { +@Mixin(GuiGraphicsExtractor.class) +public interface GuiGraphicsExtractorInvoker { @Invoker - void invokeSubmitColoredRectangle(RenderPipeline pipeline, TextureSetup textureSetup, int x0, int y0, int x1, int y1, int colour1, @Nullable Integer colour2); + void invokeInnerFill(RenderPipeline pipeline, TextureSetup textureSetup, int x0, int y0, int x1, int y1, int colour1, @Nullable Integer colour2); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/accessors/GuiInvoker.java b/src/main/java/de/hysky/skyblocker/mixins/accessors/GuiInvoker.java index 35b1dbe827..fb39fb0192 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/accessors/GuiInvoker.java +++ b/src/main/java/de/hysky/skyblocker/mixins/accessors/GuiInvoker.java @@ -1,7 +1,7 @@ package de.hysky.skyblocker.mixins.accessors; import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.world.scores.Objective; import org.jspecify.annotations.Nullable; @@ -16,5 +16,5 @@ public interface GuiInvoker { @Nullable Component getOverlayMessageString(); @Invoker("displayScoreboardSidebar") - void skyblocker$renderSidebar(GuiGraphics context, Objective objective); + void extractSidebar(GuiGraphicsExtractor graphics, Objective objective); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/accessors/MinecraftAccessor.java b/src/main/java/de/hysky/skyblocker/mixins/accessors/MinecraftAccessor.java index eac4bc75bf..3a647cc1de 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/accessors/MinecraftAccessor.java +++ b/src/main/java/de/hysky/skyblocker/mixins/accessors/MinecraftAccessor.java @@ -2,6 +2,8 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ProfileKeyPairManager; +import net.minecraft.client.renderer.block.BlockModelResolver; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -9,4 +11,7 @@ public interface MinecraftAccessor { @Accessor ProfileKeyPairManager getProfileKeyPairManager(); + + @Accessor + BlockModelResolver getBlockModelResolver(); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/BuildersWandPreview.java b/src/main/java/de/hysky/skyblocker/skyblock/BuildersWandPreview.java index 78bd910246..77b53d0c25 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/BuildersWandPreview.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/BuildersWandPreview.java @@ -3,7 +3,7 @@ import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.Minecraft; @@ -32,7 +32,7 @@ public class BuildersWandPreview { @Init public static void init() { - WorldRenderExtractionCallback.EVENT.register(collector -> { + LevelRenderExtractionCallback.EVENT.register(collector -> { if (!SkyblockerConfigManager.get().helpers.buildersWand.enableBuildersWandPreview || !Utils.isOnSkyblock() || client.player == null) return; if (!Utils.isInPrivateIsland() && !Utils.isInGarden()) return; if (!(client.hitResult instanceof BlockHitResult blockHitResult) || blockHitResult.getType() != HitResult.Type.BLOCK) return; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/CallAutocomplete.java b/src/main/java/de/hysky/skyblocker/skyblock/CallAutocomplete.java index 5246cfa50d..698c2dfd2d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/CallAutocomplete.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/CallAutocomplete.java @@ -1,7 +1,7 @@ package de.hysky.skyblocker.skyblock; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; import java.io.InputStream; import java.util.List; @@ -46,10 +46,10 @@ private static void loadCallNames() { .toList(); commandNode = literal("call") - .requires(fccs -> Utils.isOnSkyblock()) + .requires(_ -> Utils.isOnSkyblock()) .executes(CommandUtils.noOp) .then(argument("contact", StringArgumentType.greedyString()) - .suggests((context, builder) -> SharedSuggestionProvider.suggest(suggestions, builder)) + .suggests((_, builder) -> SharedSuggestionProvider.suggest(suggestions, builder)) .executes(CommandUtils.noOp)) .build(); } catch (Exception e) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/CatPicture.java b/src/main/java/de/hysky/skyblocker/skyblock/CatPicture.java index c25895346c..9ea36731b6 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/CatPicture.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/CatPicture.java @@ -4,24 +4,22 @@ import com.mojang.math.Axis; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.annotations.Init; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import de.hysky.skyblocker.utils.render.state.EmptyRenderState; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.SubmitNodeCollector; -import net.minecraft.client.renderer.block.model.BlockStateModel; import net.minecraft.client.renderer.entity.state.EntityRenderState; +import net.minecraft.client.renderer.entity.state.ItemFrameRenderState; import net.minecraft.client.renderer.rendertype.RenderTypes; -import net.minecraft.client.renderer.state.LevelRenderState; +import net.minecraft.client.renderer.state.level.LevelRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.resources.model.BlockStateDefinitions; import net.minecraft.resources.Identifier; import net.minecraft.util.CommonColors; -import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.util.LightCoordsUtil; import net.minecraft.world.phys.Vec3; import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.mixins.accessors.MinecraftAccessor; import de.hysky.skyblocker.utils.Location; import de.hysky.skyblocker.utils.Utils; @@ -32,21 +30,19 @@ public class CatPicture { @Init public static void init() { - WorldRenderExtractionCallback.EVENT.register(CatPicture::extractRendering); + LevelRenderExtractionCallback.EVENT.register(CatPicture::extractRendering); } private static void extractRendering(PrimitiveCollector collector) { // TODO Bring back culling eventually, maybe just include more context in the collector if (SkyblockerConfigManager.get().misc.cat && Utils.getLocation() == Location.HUB) { - collector.submitVanilla(EmptyRenderState.INSTANCE, CatPicture::render); + collector.submitVanilla(EmptyRenderState.INSTANCE, CatPicture::extractRenderState); } } - @SuppressWarnings("deprecation") - private static void render(EmptyRenderState state, LevelRenderState worldState, SubmitNodeCollector commandQueue) { - // Vanilla does this in the ItemFrameEntityRenderer - BlockState blockState = BlockStateDefinitions.getItemFrameFakeState(false, true); - BlockStateModel blockStateModel = Minecraft.getInstance().getBlockRenderer().getBlockModel(blockState); + private static void extractRenderState(EmptyRenderState state, LevelRenderState worldState, SubmitNodeCollector commandQueue) { + ItemFrameRenderState itemFrameState = new ItemFrameRenderState(); + ((MinecraftAccessor) Minecraft.getInstance()).getBlockModelResolver().updateForItemFrame(itemFrameState.frameModel, false, true); PoseStack matrices = new PoseStack(); matrices.pushPose(); @@ -54,17 +50,7 @@ private static void render(EmptyRenderState state, LevelRenderState worldState, matrices.mulPose(Axis.YP.rotationDegrees(180)); // Render Item Frame - commandQueue.submitBlockModel( - matrices, - RenderTypes.entitySolidZOffsetForward(TextureAtlas.LOCATION_BLOCKS), - blockStateModel, - 1f, - 1f, - 1f, - LightTexture.FULL_BRIGHT, - OverlayTexture.NO_OVERLAY, - EntityRenderState.NO_OUTLINE - ); + itemFrameState.frameModel.submitWithZOffset(matrices, commandQueue, LightCoordsUtil.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, EntityRenderState.NO_OUTLINE); // Render Kitty matrices.translate(1, 1, 0); @@ -72,10 +58,10 @@ private static void render(EmptyRenderState state, LevelRenderState worldState, commandQueue.submitCustomGeometry(matrices, RenderTypes.text(TEXTURE), (matricesEntry, buffer) -> { float z = 1F - 1 / 16f - 1 / 2048f; - buffer.addVertex(matricesEntry, 0.0F, 1, z).setColor(CommonColors.WHITE).setUv(0.0F, 1.0F).setLight(LightTexture.FULL_BRIGHT); - buffer.addVertex(matricesEntry, 1, 1, z).setColor(CommonColors.WHITE).setUv(1.0F, 1.0F).setLight(LightTexture.FULL_BRIGHT); - buffer.addVertex(matricesEntry, 1, 0.0F, z).setColor(CommonColors.WHITE).setUv(1.0F, 0.0F).setLight(LightTexture.FULL_BRIGHT); - buffer.addVertex(matricesEntry, 0.0F, 0.0F, z).setColor(CommonColors.WHITE).setUv(0.0F, 0.0F).setLight(LightTexture.FULL_BRIGHT); + buffer.addVertex(matricesEntry, 0.0F, 1, z).setColor(CommonColors.WHITE).setUv(0.0F, 1.0F).setLight(LightCoordsUtil.FULL_BRIGHT); + buffer.addVertex(matricesEntry, 1, 1, z).setColor(CommonColors.WHITE).setUv(1.0F, 1.0F).setLight(LightCoordsUtil.FULL_BRIGHT); + buffer.addVertex(matricesEntry, 1, 0.0F, z).setColor(CommonColors.WHITE).setUv(1.0F, 0.0F).setLight(LightCoordsUtil.FULL_BRIGHT); + buffer.addVertex(matricesEntry, 0.0F, 0.0F, z).setColor(CommonColors.WHITE).setUv(0.0F, 0.0F).setLight(LightCoordsUtil.FULL_BRIGHT); }); matrices.popPose(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/ChestValue.java b/src/main/java/de/hysky/skyblocker/skyblock/ChestValue.java index e36fe8af42..93dce8bbf3 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/ChestValue.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/ChestValue.java @@ -84,7 +84,7 @@ public class ChestValue { @Init public static void init() { - ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + ScreenEvents.AFTER_INIT.register((_, screen, _, _) -> { hideChestNameLabel = false; if (Utils.isOnSkyblock() && screen instanceof ContainerScreen genericContainerScreen) { Component title = screen.getTitle(); @@ -93,7 +93,7 @@ public static void init() { if (chestType != null) { if (SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator) { - ScreenEvents.afterTick(screen).register(ignored -> { + ScreenEvents.afterTick(screen).register(_ -> { Component dungeonChestProfit = getRewardChestProfit(genericContainerScreen.getMenu(), chestType); if (dungeonChestProfit != null) addValueToContainer(genericContainerScreen, dungeonChestProfit, title); @@ -101,10 +101,10 @@ public static void init() { } } else if (SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue && !titleString.equals("SkyBlock Menu")) { ScreenType screenType = determineScreenType(titleString); - Screens.getButtons(screen).add(Button + Screens.getWidgets(screen).add(Button .builder(Component.literal("$"), buttonWidget -> { - Screens.getButtons(screen).remove(buttonWidget); - ScreenEvents.afterTick(screen).register(ignored -> { + Screens.getWidgets(screen).remove(buttonWidget); + ScreenEvents.afterTick(screen).register(_ -> { Component chestValue = getChestValue(genericContainerScreen.getMenu(), screenType); if (chestValue != null) { addValueToContainer(genericContainerScreen, chestValue, title); @@ -321,7 +321,7 @@ public static DoubleBooleanPair computeKuudraKeyPrice(String kuudraKeyName) { String source = coinsLine.split(":")[1]; try { value += NumberFormat.getNumberInstance(java.util.Locale.US).parse(source.trim()).doubleValue(); - } catch (ParseException e) { + } catch (ParseException _) { LOGGER.warn("[Skyblocker] Failed to parse `{}`", source); } continue; @@ -383,7 +383,7 @@ static Component getValueText(long value, boolean hasIncompleteData) { } private static void addValueToContainer(ContainerScreen genericContainerScreen, Component chestValue, Component title) { - Screens.getButtons(genericContainerScreen).removeIf(ChestValueTextWidget.class::isInstance); + Screens.getWidgets(genericContainerScreen).removeIf(ChestValueTextWidget.class::isInstance); int backgroundWidth = ((AbstractContainerScreenAccessor) genericContainerScreen).getImageWidth(); int y = ((AbstractContainerScreenAccessor) genericContainerScreen).getY(); int x = ((AbstractContainerScreenAccessor) genericContainerScreen).getX(); @@ -393,11 +393,11 @@ private static void addValueToContainer(ContainerScreen genericContainerScreen, StringWidget chestValueWidget = new ChestValueTextWidget(chestValueWidth, textRenderer.lineHeight, chestValue, textRenderer); chestValueWidget.setPosition(x + backgroundWidth - chestValueWidget.getWidth() - 4, y + 6); - Screens.getButtons(genericContainerScreen).add(chestValueWidget); + Screens.getWidgets(genericContainerScreen).add(chestValueWidget); ChestValueTextWidget chestTitleWidget = new ChestValueTextWidget(backgroundWidth - 8 - chestValueWidth - 2, textRenderer.lineHeight, title.copy().withStyle(Style.EMPTY.withColor(4210752)), textRenderer); chestTitleWidget.setPosition(x + 8, y + 6); - Screens.getButtons(genericContainerScreen).add(chestTitleWidget); + Screens.getWidgets(genericContainerScreen).add(chestTitleWidget); } private static ScreenType determineScreenType(String rawTitleString) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java b/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java index 9cd800d969..a914f80bd5 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java @@ -77,10 +77,10 @@ public static void compactDamage(ArmorStand entity) { entity.skyblocker$setCustomName(prettierCustomName); } - /// We want precision to signify the *number of significant digits*, not the number of digits after the decimal. - /// For example: - /// 123,456,789 (precision 3) -> 123M - /// 12,345 (precision 4) -> 1.234k + // We want precision to signify the *number of significant digits*, not the number of digits after the decimal. + // For example: + // 123,456,789 (precision 3) -> 123M + // 12,345 (precision 4) -> 1.234k @VisibleForTesting static String prettifyDamageNumber(final long damage, final int maxPrecision) { long targetDamage = damage; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/GyroOverlay.java b/src/main/java/de/hysky/skyblocker/skyblock/GyroOverlay.java index 6f38d529d7..b775a3c4af 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/GyroOverlay.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/GyroOverlay.java @@ -3,7 +3,7 @@ import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import java.awt.Color; import java.util.Locale; @@ -28,7 +28,7 @@ public class GyroOverlay { @Init public static void init() { configCallback(SkyblockerConfigManager.get().uiAndVisuals.gyroOverlay.gyroOverlayColor); - WorldRenderExtractionCallback.EVENT.register(GyroOverlay::extractRendering); + LevelRenderExtractionCallback.EVENT.register(GyroOverlay::extractRendering); } // render diff --git a/src/main/java/de/hysky/skyblocker/skyblock/HealthBars.java b/src/main/java/de/hysky/skyblocker/skyblock/HealthBars.java index 2c57f6d8d0..574113c563 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/HealthBars.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/HealthBars.java @@ -6,7 +6,7 @@ import de.hysky.skyblocker.utils.Formatters; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.RenderHelper; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import it.unimi.dsi.fastutil.objects.Object2FloatMap; import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap; @@ -48,8 +48,8 @@ public class HealthBars { @Init public static void init() { - ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> reset()); - WorldRenderExtractionCallback.EVENT.register(HealthBars::extractRendering); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); + LevelRenderExtractionCallback.EVENT.register(HealthBars::extractRendering); ClientEntityEvents.ENTITY_UNLOAD.register(HealthBars::onEntityDespawn); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/HideStatusEffectOverlay.java b/src/main/java/de/hysky/skyblocker/skyblock/HideStatusEffectOverlay.java index 5b932a5e36..2a9b5df43a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/HideStatusEffectOverlay.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/HideStatusEffectOverlay.java @@ -9,8 +9,8 @@ public final class HideStatusEffectOverlay { @Init public static void init() { - HudElementRegistry.replaceElement(VanillaHudElements.STATUS_EFFECTS, hudElement -> { - if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.hideStatusEffectOverlay) return (context, tickCounter) -> {}; + HudElementRegistry.replaceElement(VanillaHudElements.MOB_EFFECTS, hudElement -> { + if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.hideStatusEffectOverlay) return (_, _) -> {}; return hudElement; }); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/InventorySearch.java b/src/main/java/de/hysky/skyblocker/skyblock/InventorySearch.java index 14ba4c0623..f581581eb8 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/InventorySearch.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/InventorySearch.java @@ -11,7 +11,7 @@ import net.fabricmc.fabric.api.client.screen.v1.Screens; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.StringWidget; import net.minecraft.client.gui.screens.Screen; @@ -33,14 +33,14 @@ public class InventorySearch { @Init public static void init() { - ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + ScreenEvents.AFTER_INIT.register((_, screen, _, _) -> { UIAndVisualsConfig.InventorySearchConfig inventorySearchConfig = SkyblockerConfigManager.get().uiAndVisuals.inventorySearch; if (!inventorySearchConfig.enabled.isEnabled() || !(screen instanceof AbstractContainerScreen handledScreen)) return; openedHandledScreen = null; - if (inventorySearchConfig.clickableText) Screens.getButtons(handledScreen).add(new SearchTextWidget(handledScreen)); + if (inventorySearchConfig.clickableText) Screens.getWidgets(handledScreen).add(new SearchTextWidget(handledScreen)); - ScreenKeyboardEvents.allowKeyPress(handledScreen).register((screen1, input) -> { + ScreenKeyboardEvents.allowKeyPress(handledScreen).register((_, input) -> { if (input.key() == (inventorySearchConfig.ctrlK ? GLFW.GLFW_KEY_K : GLFW.GLFW_KEY_F) && input.hasControlDownWithQuirk()) { InventorySearch.showSearchBar(handledScreen); return false; @@ -54,8 +54,8 @@ public static void showSearchBar(AbstractContainerScreen handledScreen) { if (handledScreen == openedHandledScreen) return; openedHandledScreen = handledScreen; EditBox textFieldWidget = getTextFieldWidget(handledScreen); - Screens.getButtons(handledScreen).addFirst(textFieldWidget); - Screens.getButtons(handledScreen).removeIf(button -> button instanceof SearchTextWidget); // remove search text + Screens.getWidgets(handledScreen).addFirst(textFieldWidget); + Screens.getWidgets(handledScreen).removeIf(button -> button instanceof SearchTextWidget); // remove search text handledScreen.setFocused(textFieldWidget); ScreenEvents.remove(handledScreen).register(InventorySearch::onScreenClosed); @@ -76,7 +76,7 @@ public static boolean isSearching() { } public static boolean slotMatches(Slot slot) { - return slotToMatch.computeIfAbsent(slot.index, i -> slot.hasItem() && + return slotToMatch.computeIfAbsent(slot.index, _ -> slot.hasItem() && (slot.getItem().getHoverName().getString().toLowerCase(Locale.ENGLISH).contains(search) || ItemUtils.getLoreLineIf(slot.getItem(), s -> s.toLowerCase(Locale.ENGLISH).contains(search)) != null)); } @@ -119,14 +119,14 @@ public void onClick(MouseButtonEvent click, boolean doubled) { } @Override - public void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delta) { + public void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { if (isHovered() != hoveredState) { hoveredState = active = isHovered(); if (hoveredState) setMessage(underlinedText); else setMessage(normalText); } - super.renderWidget(context, mouseX, mouseY, delta); + super.extractWidgetRenderState(graphics, mouseX, mouseY, a); } } @@ -141,9 +141,9 @@ public SearchTextFieldWidget(Font textRenderer, Component message) { } @Override - public void renderWidget(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) { - super.renderWidget(context, mouseX, mouseY, deltaTicks); - context.drawCenteredString(textRenderer, message, getX() + width / 2, getY() - 1 - textRenderer.lineHeight, CommonColors.WHITE); + public void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractWidgetRenderState(graphics, mouseX, mouseY, a); + graphics.centeredText(textRenderer, message, getX() + width / 2, getY() - 1 - textRenderer.lineHeight, CommonColors.WHITE); } @Override diff --git a/src/main/java/de/hysky/skyblocker/skyblock/ItemPickupWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/ItemPickupWidget.java index f4932b06e4..bcea9d3730 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/ItemPickupWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/ItemPickupWidget.java @@ -8,6 +8,7 @@ import de.hysky.skyblocker.skyblock.tabhud.util.Ico; import de.hysky.skyblocker.skyblock.tabhud.widget.ElementBasedWidget; import de.hysky.skyblocker.skyblock.tabhud.widget.element.SeparatorElement; +import de.hysky.skyblocker.utils.FlexibleItemStack; import de.hysky.skyblocker.utils.Formatters; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Location; @@ -52,9 +53,9 @@ public ItemPickupWidget() { instance = this; ClientReceiveMessageEvents.ALLOW_GAME.register(instance::onChatMessage); - ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> changingLobby = true); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> changingLobby = true); // Make changingLobby true for a short period while the player loads into a new lobby and their items are loading - SkyblockEvents.LOCATION_CHANGE.register(location -> Scheduler.INSTANCE.schedule(() -> changingLobby = false, LOBBY_CHANGE_DELAY)); + SkyblockEvents.LOCATION_CHANGE.register(_ -> Scheduler.INSTANCE.schedule(() -> changingLobby = false, LOBBY_CHANGE_DELAY)); } public static ItemPickupWidget getInstance() { @@ -64,7 +65,7 @@ public static ItemPickupWidget getInstance() { /** * Searches the NEU REPO for the item linked to the name */ - private static ItemStack getItem(String itemName) { + private static FlexibleItemStack getItem(String itemName) { if (NEURepoManager.isLoading() || !ItemRepository.filesImported()) return ItemUtils.getNamedPlaceholder(itemName); return NEURepoManager.getItemByName(itemName) .stream() @@ -87,7 +88,7 @@ private boolean onChatMessage(Component message, boolean overlay) { Matcher matcher = CHANGE_REGEX.matcher(hoverMessage); while (matcher.find()) { - ItemStack item = getItem(matcher.group(3)); + ItemStack item = getItem(matcher.group(3)).getStackOrThrow(); //positive int existingCount = 0; if (matcher.group(1).equals("+")) { @@ -152,7 +153,7 @@ public void updateContent() { addedCount.remove(item); continue; } - addSimpleIcoText(entry.item, itemName, ChatFormatting.GREEN, Formatters.DIFF_NUMBERS.format(entry.amount)); + addSimpleIcoText(new FlexibleItemStack(entry.item), itemName, ChatFormatting.GREEN, Formatters.DIFF_NUMBERS.format(entry.amount)); } //add negative changes for (String item : removedCount.keySet()) { @@ -162,7 +163,7 @@ public void updateContent() { removedCount.remove(item); continue; } - addSimpleIcoText(entry.item, itemName, ChatFormatting.RED, Formatters.DIFF_NUMBERS.format(entry.amount)); + addSimpleIcoText(new FlexibleItemStack(entry.item), itemName, ChatFormatting.RED, Formatters.DIFF_NUMBERS.format(entry.amount)); } if (split && !(this.addedSackCount.isEmpty() && this.removedSackCount.isEmpty())) { // Remove the borders and some random 8 value I do not know where that comes from from the width of the widget to make it fit. @@ -174,7 +175,7 @@ public void updateContent() { addedSackCount.remove(item); continue; } - addSimpleIcoText(entry.item, itemName, ChatFormatting.GREEN, Formatters.DIFF_NUMBERS.format(entry.amount)); + addSimpleIcoText(new FlexibleItemStack(entry.item), itemName, ChatFormatting.GREEN, Formatters.DIFF_NUMBERS.format(entry.amount)); } for (String item : removedSackCount.keySet()) { ChangeData entry = removedSackCount.get(item); @@ -183,7 +184,7 @@ public void updateContent() { removedSackCount.remove(item); continue; } - addSimpleIcoText(entry.item, itemName, ChatFormatting.RED, Formatters.DIFF_NUMBERS.format(entry.amount)); + addSimpleIcoText(new FlexibleItemStack(entry.item), itemName, ChatFormatting.RED, Formatters.DIFF_NUMBERS.format(entry.amount)); } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/JoinInstanceAutocomplete.java b/src/main/java/de/hysky/skyblocker/skyblock/JoinInstanceAutocomplete.java index 5a9a4c244c..b9d0c44072 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/JoinInstanceAutocomplete.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/JoinInstanceAutocomplete.java @@ -19,8 +19,8 @@ import java.util.concurrent.Executors; import java.util.stream.Collectors; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; /** * the mixin {@link de.hysky.skyblocker.mixins.ClientboundCommandsPacketMixin} @@ -43,7 +43,7 @@ public static void init() { JsonObject obj = JsonParser.parseString(json).getAsJsonObject(); instanceMap = obj.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getAsString())); - joinInstanceCommand = buildCommand("joininstance", s -> true); + joinInstanceCommand = buildCommand("joininstance", _ -> true); dungeonCommand = buildCommand("joindungeon", s -> instanceMap.get(s).equalsIgnoreCase("Catacombs")); kuudraCommand = buildCommand("joinkuudra", s -> instanceMap.get(s).equalsIgnoreCase("Kuudra")); @@ -55,10 +55,10 @@ public static void init() { private static LiteralCommandNode buildCommand(String command, java.util.function.Predicate filter) { return literal(command) - .requires(source -> Utils.isOnSkyblock()) + .requires(_ -> Utils.isOnSkyblock()) .executes(CommandUtils.noOp) .then(argument("instance", StringArgumentType.word()) - .suggests((context, builder) -> SharedSuggestionProvider.suggest( + .suggests((_, builder) -> SharedSuggestionProvider.suggest( instanceMap.keySet().stream().filter(filter).sorted(), builder)) .executes(CommandUtils.noOp)) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/NightVisionCommand.java b/src/main/java/de/hysky/skyblocker/skyblock/NightVisionCommand.java index 602071f7fc..2516b9a186 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/NightVisionCommand.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/NightVisionCommand.java @@ -11,8 +11,8 @@ import net.minecraft.commands.CommandBuildContext; import net.minecraft.network.chat.Component; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; public class NightVisionCommand { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java b/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java index 7ea11faed6..01dac1cbbe 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java @@ -5,6 +5,7 @@ import de.hysky.skyblocker.skyblock.item.PetInfo; import de.hysky.skyblocker.skyblock.item.SkyblockItemRarity; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; +import de.hysky.skyblocker.utils.FlexibleItemStack; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.RegexUtils; import de.hysky.skyblocker.utils.Utils; @@ -51,12 +52,12 @@ public class PetCache { public static void init() { CACHED_PETS.load(); - ScreenEvents.BEFORE_INIT.register((_client, screen, _scaledWidth, _scaledHeight) -> { + ScreenEvents.BEFORE_INIT.register((_, screen, _, _) -> { if (Utils.isOnSkyblock() && screen instanceof ContainerScreen genericContainerScreen) { if (genericContainerScreen.getTitle().getString().startsWith("Pets")) { shouldLook4Pets = true; - ScreenEvents.afterTick(screen).register(screen1 -> { + ScreenEvents.afterTick(screen).register(_ -> { if (shouldLook4Pets) { for (Slot slot : genericContainerScreen.getMenu().slots) { ItemStack stack = slot.getItem(); @@ -128,7 +129,7 @@ private static boolean onMessage(Component text, boolean overlay) { //The index has nothing to do with the codepoint's position so we must track it ourselves //The visitor automatically folds section symbols into regular Style instances so we don't need to care about those either :) - ordered.accept((index, style, codePoint) -> { + ordered.accept((_, style, _) -> { if (codePointIndex.intValue() == nameIndex) { color.setValue(style.getColor().getValue()); @@ -150,8 +151,9 @@ private static boolean onMessage(Component text, boolean overlay) { //Find pet in NEU repo ItemStack stack = ItemRepository.getItemsStream() - .filter(s -> s.getHoverName().getString().contains("] " + name)) + .filter(s -> s.getStackOrThrow().getHoverName().getString().contains("] " + name)) .findFirst() + .map(FlexibleItemStack::getStackOrThrow) .orElse(ItemStack.EMPTY); if (!stack.isEmpty()) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/RngMeterAutocomplete.java b/src/main/java/de/hysky/skyblocker/skyblock/RngMeterAutocomplete.java index 6e482ce141..22cf52ee61 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/RngMeterAutocomplete.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/RngMeterAutocomplete.java @@ -1,7 +1,7 @@ package de.hysky.skyblocker.skyblock; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; import java.util.HashMap; import java.util.List; @@ -50,10 +50,10 @@ public static void init() { private static LiteralCommandNode createCommandNode(String command) { return literal(command) - .requires(source -> Utils.isOnSkyblock()) + .requires(_ -> Utils.isOnSkyblock()) .executes(CommandUtils.noOp) .then(argument("type", StringArgumentType.string()) - .suggests((context, builder) -> SharedSuggestionProvider.suggest(rngMeters.keySet(), builder)) + .suggests((_, builder) -> SharedSuggestionProvider.suggest(rngMeters.keySet(), builder)) .executes(CommandUtils.noOp) .then(argument("subtype", StringArgumentType.string()) .suggests((context, builder) -> SharedSuggestionProvider.suggest(rngMeters.getOrDefault(StringArgumentType.getString(context, "type"), List.of()), builder)) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/SackItemAutocomplete.java b/src/main/java/de/hysky/skyblocker/skyblock/SackItemAutocomplete.java index 1cd4de27c4..fe43728b26 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/SackItemAutocomplete.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/SackItemAutocomplete.java @@ -1,7 +1,7 @@ package de.hysky.skyblocker.skyblock; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; import java.io.InputStream; import java.util.List; @@ -71,10 +71,10 @@ private static void loadSackItems() { private static LiteralCommandNode createCommandNode(String command, Set sackItems) { return literal(command) - .requires(fccs -> Utils.isOnSkyblock()) + .requires(_ -> Utils.isOnSkyblock()) .executes(CommandUtils.noOp) .then(argument("item", StringArgumentType.greedyString()) - .suggests((context, builder) -> SharedSuggestionProvider.suggest(sackItems, builder)) + .suggests((_, builder) -> SharedSuggestionProvider.suggest(sackItems, builder)) .then(argument("amount", IntegerArgumentType.integer(0))) // Adds a nice text to the suggestion when any number is entered after the item string .executes(CommandUtils.noOp) ) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/Tips.java b/src/main/java/de/hysky/skyblocker/skyblock/Tips.java index 5ce90a75b8..8bc9ecfc03 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/Tips.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/Tips.java @@ -21,7 +21,7 @@ import java.util.List; import java.util.function.Supplier; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; public class Tips { private static final String modVersion = SkyblockerMod.VERSION.split("\\+")[0]; @@ -122,7 +122,7 @@ private static int disableTips(CommandContext context private static void sendNextTip() { Minecraft client = Minecraft.getInstance(); if (client.player != null && SkyblockerConfigManager.get().general.enableTips && !sentTip) { - client.player.displayClientMessage(tipMessage(nextTip()), false); + client.player.sendSystemMessage(tipMessage(nextTip())); sentTip = true; } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/ViewstashAutocomplete.java b/src/main/java/de/hysky/skyblocker/skyblock/ViewstashAutocomplete.java index f3c7dfa419..d604dea58a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/ViewstashAutocomplete.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/ViewstashAutocomplete.java @@ -8,16 +8,16 @@ import net.minecraft.commands.SharedSuggestionProvider; import java.util.stream.Stream; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; public class ViewstashAutocomplete { public static LiteralCommandNode getCommandNode() { return literal("viewstash") - .requires(fabricClientCommandSource -> Utils.isOnSkyblock()) + .requires(_ -> Utils.isOnSkyblock()) .executes(CommandUtils.noOp) .then(argument("stash", StringArgumentType.word()) - .suggests((context, builder) -> SharedSuggestionProvider.suggest(Stream.of("material", "item"), builder)) + .suggests((_, builder) -> SharedSuggestionProvider.suggest(Stream.of("material", "item"), builder)) .executes(CommandUtils.noOp) ).build(); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/WardrobeKeybinds.java b/src/main/java/de/hysky/skyblocker/skyblock/WardrobeKeybinds.java index e36432d5eb..d2dc0d2439 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/WardrobeKeybinds.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/WardrobeKeybinds.java @@ -11,7 +11,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.network.chat.Component; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -30,12 +30,12 @@ public WardrobeKeybinds() { @Init public static void init() { - ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + ScreenEvents.AFTER_INIT.register((client, screen, _, _) -> { if (!(screen instanceof AbstractContainerScreen handledScreen) || !INSTANCE.test(handledScreen) || !INSTANCE.isEnabled() || client.gameMode == null) return; - ScreenKeyboardEvents.allowKeyPress(handledScreen).register((ignored, keyInput) -> + ScreenKeyboardEvents.allowKeyPress(handledScreen).register((_, keyInput) -> allowInput(client, handledScreen, keybinding -> keybinding.matches(keyInput)) ); - ScreenMouseEvents.allowMouseClick(handledScreen).register((ignored, click) -> + ScreenMouseEvents.allowMouseClick(handledScreen).register((_, click) -> allowInput(client, handledScreen, keybinding -> keybinding.matchesMouse(click)) ); }); @@ -58,7 +58,7 @@ private static boolean allowInput(Minecraft client, AbstractContainerScreen h // This prevents usage when the inventory hasn't loaded fully or when the slot pressed is locked or when the slot has no armor (which would be meaningless to click) if (!itemStack.is(Items.PINK_DYE) && !itemStack.is(Items.LIME_DYE)) return true; assert client.gameMode != null; - client.gameMode.handleInventoryMouseClick(handledScreen.getMenu().containerId, i, GLFW.GLFW_MOUSE_BUTTON_1, ClickType.PICKUP, client.player); + client.gameMode.handleContainerInput(handledScreen.getMenu().containerId, i, GLFW.GLFW_MOUSE_BUTTON_1, ContainerInput.PICKUP, client.player); return false; } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/WarpAutocomplete.java b/src/main/java/de/hysky/skyblocker/skyblock/WarpAutocomplete.java index 45ca3f2cd2..ebc4089c50 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/WarpAutocomplete.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/WarpAutocomplete.java @@ -35,8 +35,8 @@ import java.util.concurrent.Executors; import java.util.stream.Stream; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; /** * the mixin {@link de.hysky.skyblocker.mixins.ClientboundCommandsPacketMixin} @@ -84,7 +84,7 @@ private static void getWarpsFromFile() { JsonObject object; try (BufferedReader reader = Files.newBufferedReader(FILE)) { object = SkyblockerMod.GSON.fromJson(reader, JsonObject.class); - } catch (NoSuchFileException e) { + } catch (NoSuchFileException _) { return Object2BooleanMaps.emptyMap(); } catch (Exception e) { LOGGER.error("[Skyblocker] Failed to read warp autocomplete file", e); @@ -96,10 +96,10 @@ private static void getWarpsFromFile() { private static void createCommandNode(Object2BooleanMap warps) { commandNode = literal("warp") - .requires(fabricClientCommandSource -> Utils.isOnSkyblock()) + .requires(_ -> Utils.isOnSkyblock()) .executes(CommandUtils.noOp) .then(argument("destination", StringArgumentType.greedyString()) - .suggests((context, builder) -> SharedSuggestionProvider.suggest(getEligibleWarps(warps), builder)) + .suggests((_, builder) -> SharedSuggestionProvider.suggest(getEligibleWarps(warps), builder)) .executes(CommandUtils.noOp) ).build(); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelper.java index 3c94850db9..3b5382cc85 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelper.java @@ -45,12 +45,12 @@ public class AccessoriesHelper { @Init public static void init() { COLLECTED_ACCESSORIES.init(); - ScreenEvents.AFTER_INIT.register((_client, screen, _scaledWidth, _scaledHeight) -> { + ScreenEvents.AFTER_INIT.register((_, screen, _, _) -> { if (Utils.isOnSkyblock() && TooltipInfoType.ACCESSORIES.isTooltipEnabled() && !Utils.getProfileId().isEmpty() && screen instanceof ContainerScreen genericContainerScreen) { Matcher matcher = ACCESSORY_BAG_TITLE.matcher(genericContainerScreen.getTitle().getString()); if (matcher.matches()) { - ScreenEvents.afterTick(screen).register(_screen -> { + ScreenEvents.afterTick(screen).register(_ -> { ChestMenu handler = genericContainerScreen.getMenu(); int page = matcher.group("page") != null ? Integer.parseInt(matcher.group("page")) : 1; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelperWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelperWidget.java index ce929b376a..b0699ad49c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelperWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelperWidget.java @@ -14,6 +14,8 @@ import de.hysky.skyblocker.skyblock.item.wikilookup.WikiLookupManager; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.skyblock.itemlist.recipebook.SkyblockRecipeResultButton; +import de.hysky.skyblocker.skyblock.tabhud.util.Ico; +import de.hysky.skyblocker.utils.FlexibleItemStack; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.NEURepoManager; import de.hysky.skyblocker.utils.container.ContainerSolverManager; @@ -22,10 +24,10 @@ import net.fabricmc.fabric.api.client.screen.v1.Screens; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.LoadingDotsText; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.input.MouseButtonEvent; -import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.events.GuiEventListener; import com.mojang.blaze3d.platform.cursor.CursorTypes; import net.minecraft.client.gui.components.WidgetSprites; @@ -36,6 +38,7 @@ import net.minecraft.client.gui.screens.recipebook.RecipeBookTabButton; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.AbstractContainerWidget; +import net.minecraft.client.gui.components.AbstractScrollArea; import net.minecraft.client.gui.components.CycleButton; import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.client.gui.layouts.GridLayout; @@ -91,7 +94,7 @@ static void attachToScreen(ContainerScreen screen) { if (!SkyblockerConfigManager.get().general.itemTooltip.enableAccessoriesHelper || !SkyblockerConfigManager.get().helpers.enableAccessoriesHelperWidget) return; final AccessoriesHelperWidget widget = new AccessoriesHelperWidget(); widget.setY((screen.height - widget.getHeight()) / 2); - Screens.getButtons(screen).add(widget); + Screens.getWidgets(screen).add(widget); final int previousX = ((AbstractContainerScreenAccessor) screen).getX(); final int offset = Math.max(180 - previousX, 0); TabButton tabButton = new TabButton(button -> { @@ -109,12 +112,12 @@ static void attachToScreen(ContainerScreen screen) { page = 0; } }); - Screens.getButtons(screen).add(tabButton); + Screens.getWidgets(screen).add(tabButton); tabButton.setToggled(open); } AccessoriesHelperWidget() { - super(0, 0, 147, 182, CommonComponents.EMPTY); + super(0, 0, 147, 182, CommonComponents.EMPTY, AbstractScrollArea.defaultSettings(4)); this.layout = new FrameLayout(getWidth() - BORDER_SIZE * 2, getHeight() - BORDER_SIZE * 2); LinearLayout mainLayout = layout.addChild(LinearLayout.vertical()); mainLayout.defaultCellSetting().alignHorizontallyCenter(); @@ -135,7 +138,7 @@ static void attachToScreen(ContainerScreen screen) { mainLayout.addChild(CycleButton.builder(f -> Component.translatable(f.toString()), filter) .withValues(Filter.values()) - .create(0, 0, filterWidth, 16, Component.translatable("skyblocker.accessoryHelper.filter"), (b, v) -> { + .create(0, 0, filterWidth, 16, Component.translatable("skyblocker.accessoryHelper.filter"), (_, v) -> { filter = v; updateFilter(); changePage(0); @@ -143,7 +146,7 @@ static void attachToScreen(ContainerScreen screen) { ); mainLayout.addChild(CycleButton.booleanBuilder(Component.translatable("skyblocker.accessoryHelper.highestTierOnly"), Component.translatable("skyblocker.accessoryHelper.allTiers"), showHighestTierOnly) .displayOnlyValue() - .create(0, 0, filterWidth, 16, CommonComponents.EMPTY, (button, value) -> { + .create(0, 0, filterWidth, 16, CommonComponents.EMPTY, (_, value) -> { showHighestTierOnly = value; updateFilter(); changePage(0); @@ -185,7 +188,7 @@ private void refreshData() { private void updateFilter() { Predicate predicate = switch (filter) { - case ALL -> info -> true; + case ALL -> _ -> true; case MISSING -> info -> info.highestOwned().isEmpty(); case UPGRADES -> info -> info.highestOwned().isPresent() && info.accessory().tier() > info.highestOwned().get().tier(); }; @@ -202,7 +205,7 @@ private void updateFilter() { * Checks bazaar, lbin and craft cost. */ private static OptionalDouble getPrice(Accessory acc) { - ItemStack stack = ItemRepository.getItemStack(acc.id()); + FlexibleItemStack stack = ItemRepository.getItemStack(acc.id()); if (stack == null) return OptionalDouble.empty(); DoubleBooleanPair optionalPrice = ItemUtils.getItemPrice(stack); double price; @@ -251,19 +254,19 @@ public void setY(int y) { } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) { - context.blitSprite(RenderPipelines.GUI_TEXTURED, TEXTURE, getX(), getY(), getWidth(), getHeight()); + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, TEXTURE, getX(), getY(), getWidth(), getHeight()); String prevHighlighted = AccessoriesContainerSolver.INSTANCE.highlightedAccessory; AccessoriesContainerSolver.INSTANCE.highlightedAccessory = null; for (AbstractWidget widget : widgets) { - widget.render(context, mouseX, mouseY, deltaTicks); + widget.extractRenderState(graphics, mouseX, mouseY, a); } if (!ItemRepository.filesImported() || TooltipInfoType.ACCESSORIES.getData() == null) { refreshWhenDoneLoading = true; int x = getX() + getWidth() / 2; int y = getY() + getHeight() / 4; - context.drawCenteredString(Minecraft.getInstance().font, "Loading...", x, y, -1); - context.drawCenteredString(Minecraft.getInstance().font, LoadingDotsText.get(Util.getMillis()), x, y + 10, -1); + graphics.centeredText(Minecraft.getInstance().font, "Loading...", x, y, -1); + graphics.centeredText(Minecraft.getInstance().font, LoadingDotsText.get(Util.getMillis()), x, y + 10, -1); } else if (refreshWhenDoneLoading) { refreshWhenDoneLoading = false; refreshData(); @@ -305,9 +308,9 @@ public void onClick(MouseButtonEvent click, boolean doubled) { } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) { - context.blitSprite(RenderPipelines.GUI_TEXTURED, textures.get(true, isHovered()), getX(), getY(), getWidth(), getHeight()); - if (isHovered()) context.requestCursor(CursorTypes.POINTING_HAND); + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, textures.get(true, isHovered()), getX(), getY(), getWidth(), getHeight()); + if (isHovered()) graphics.requestCursor(CursorTypes.POINTING_HAND); } @Override @@ -320,20 +323,20 @@ private static class TabButton extends ImageButton { private boolean toggled; TabButton(Consumer onToggled) { - super(35, 27, RecipeBookTabButton.SPRITES, b -> {}, CommonComponents.EMPTY); + super(35, 27, RecipeBookTabButton.SPRITES, _ -> {}, CommonComponents.EMPTY); this.onToggled = onToggled; } @Override - public void renderContents(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) { + public void extractContents(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { int x = this.getX(); if (this.toggled) x -= 2; - context.blitSprite(RenderPipelines.GUI_TEXTURED, this.sprites.get(true, this.toggled), x, this.getY(), this.width, this.height); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, this.sprites.get(true, this.toggled), x, this.getY(), this.width, this.height); int offset = this.toggled ? -2 : 0; WidgetSprites buttonTextures = this.toggled ? RecipeBookPage.PAGE_FORWARD_SPRITES : RecipeBookPage.PAGE_BACKWARD_SPRITES; - context.blitSprite(RenderPipelines.GUI_TEXTURED, + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, buttonTextures.get(false, isHovered()), getX() + offset + 9, getY() + (getHeight() - 17) / 2, @@ -342,7 +345,7 @@ public void renderContents(GuiGraphics context, int mouseX, int mouseY, float de if (this.isHovered()) { - context.requestCursor(CursorTypes.POINTING_HAND); + graphics.requestCursor(CursorTypes.POINTING_HAND); } } @@ -363,16 +366,16 @@ private static class ResultButton extends SkyblockRecipeResultButton implements private void setSource(MagicPowerSource source) { this.source = source; - setDisplayStack(source.icon()); + setDisplayStack(source.icon().getStackOrThrow()); } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delta) { - super.renderWidget(context, mouseX, mouseY, delta); + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractWidgetRenderState(graphics, mouseX, mouseY, a); ItemStack stack = getDisplayStack(); if (isHovered() && stack != null && source != null) { - source.drawTooltip(context, mouseX, mouseY); - context.requestCursor(CursorTypes.POINTING_HAND); + source.extractTooltip(graphics, mouseX, mouseY); + graphics.requestCursor(CursorTypes.POINTING_HAND); } } @@ -401,7 +404,7 @@ private static class Source implements MagicPowerSource { private final AccessoryInfo info; private final @Nullable List afterSelling; - private @Nullable ItemStack icon; + private @Nullable FlexibleItemStack icon; private Source(AccessoryInfo info) { this.info = info; @@ -416,25 +419,25 @@ private Source(AccessoryInfo info) { Component translatable = Component.translatable( "skyblocker.accessoryHelper.afterSelling", ItemTooltip.getCoinsMessage(priceOpt.getAsDouble() - price.leftDouble(), 1), - accStack.getHoverName()); + accStack.getStackOrThrow().getHoverName()); return Optional.of(Minecraft.getInstance().font.split(translatable, 170)); }) .orElse(null); } @Override - public ItemStack icon() { + public FlexibleItemStack icon() { return icon != null ? icon : (icon = Optional.ofNullable(ItemRepository.getItemStack(info.accessory().id())).orElse(ItemUtils.getItemIdPlaceholder(info.accessory().id()))); } @Override - public void drawTooltip(GuiGraphics context, int mouseX, int mouseY) { + public void extractTooltip(GuiGraphicsExtractor graphics, int mouseX, int mouseY) { if (icon == null) { return; } info.highestOwned().ifPresent(owned -> AccessoriesContainerSolver.INSTANCE.highlightedAccessory = owned.id()); Minecraft client = Minecraft.getInstance(); - List tooltip = Screen.getTooltipFromItem(client, icon).stream().map(Component::getVisualOrderText).collect(Util.toMutableList()); + List tooltip = Screen.getTooltipFromItem(client, icon.getStackOrThrow()).stream().map(Component::getVisualOrderText).collect(Util.toMutableList()); tooltip.add(smoothLine.getVisualOrderText()); if (afterSelling != null) { tooltip.addAll(afterSelling); @@ -442,7 +445,7 @@ public void drawTooltip(GuiGraphics context, int mouseX, int mouseY) { } tooltip.add(wikiLine.getVisualOrderText()); tooltip.add(fandomLine.getVisualOrderText()); - context.setTooltipForNextFrame(client.font, tooltip, mouseX, mouseY, icon.get(DataComponents.TOOLTIP_STYLE)); + graphics.setTooltipForNextFrame(client.font, tooltip, mouseX, mouseY, icon.get(DataComponents.TOOLTIP_STYLE)); } @Override @@ -454,10 +457,10 @@ public double pricePerMp() { if (info.highestOwned().isPresent()) { OptionalDouble ownedPrice = getPrice(info.highestOwned().get()); price -= ownedPrice.orElse(0); - ItemStack stack = ItemRepository.getItemStack(info.highestOwned().get().id()); + FlexibleItemStack stack = ItemRepository.getItemStack(info.highestOwned().get().id()); originalMP = stack != null ? stack.getSkyblockRarity().getMP() : 0; } - ItemStack stack = ItemRepository.getItemStack(info.accessory().id()); + FlexibleItemStack stack = ItemRepository.getItemStack(info.accessory().id()); if (stack == null) return Double.MAX_VALUE; int mp = stack.getSkyblockRarity().getMP() - originalMP; return mp <= 0 ? Double.MAX_VALUE : price / mp; @@ -468,17 +471,17 @@ public void click() { if (icon == null) return; LocalPlayer player = Minecraft.getInstance().player; if (player == null) return; - WikiLookupManager.openWiki(icon, player, !Minecraft.getInstance().hasShiftDown()); + WikiLookupManager.openWiki(icon.getStackOrThrow(), player, !Minecraft.getInstance().hasShiftDown()); } } } private static class RecombobulateSource implements MagicPowerSource { - private final ItemStack icon; + private final FlexibleItemStack icon; private final double pricePerMp; private final List tooltip; private RecombobulateSource(SkyblockItemRarity rarity) { - this.icon = ItemRepository.getItemStack("RECOMBOBULATOR_3000", ItemStack.EMPTY); + this.icon = ItemRepository.getItemStack("RECOMBOBULATOR_3000", Ico.BARRIER); DoubleBooleanPair pair = ItemUtils.getItemPrice("RECOMBOBULATOR_3000"); double price = pair.rightBoolean() ? pair.leftDouble() : 6000000; int mp = rarity.recombobulate().getMP() - rarity.getMP(); @@ -493,14 +496,14 @@ private RecombobulateSource(SkyblockItemRarity rarity) { } @Override - public ItemStack icon() { + public FlexibleItemStack icon() { return icon; } @Override - public void drawTooltip(GuiGraphics context, int mouseX, int mouseY) { + public void extractTooltip(GuiGraphicsExtractor graphics, int mouseX, int mouseY) { Font textRenderer = Minecraft.getInstance().font; - context.setComponentTooltipForNextFrame(textRenderer, tooltip, mouseX, mouseY); + graphics.setComponentTooltipForNextFrame(textRenderer, tooltip, mouseX, mouseY); } @Override @@ -517,9 +520,9 @@ public void click() { } private interface MagicPowerSource { - ItemStack icon(); + FlexibleItemStack icon(); - void drawTooltip(GuiGraphics context, int mouseX, int mouseY); + void extractTooltip(GuiGraphicsExtractor graphics, int mouseX, int mouseY); double pricePerMp(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/accessories/newyearcakes/NewYearCakesHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/accessories/newyearcakes/NewYearCakesHelper.java index e1fa0f806a..9801d6c535 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/accessories/newyearcakes/NewYearCakesHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/accessories/newyearcakes/NewYearCakesHelper.java @@ -57,7 +57,7 @@ public boolean isEnabled() { public boolean addCake(int year) { if (year < 0) return false; - return cakes.computeIfAbsent(Utils.getProfile(), _profile -> new IntOpenHashSet()).add(year); + return cakes.computeIfAbsent(Utils.getProfile(), _ -> new IntOpenHashSet()).add(year); } private boolean onChatMessage(Component message, boolean overlay) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java index 0187550029..4465243286 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java @@ -9,7 +9,7 @@ import de.hysky.skyblocker.skyblock.auction.widgets.SortWidget; import de.hysky.skyblocker.skyblock.item.tooltip.info.TooltipInfoType; import de.hysky.skyblocker.utils.ItemUtils; -import de.hysky.skyblocker.utils.render.HudHelper; +import de.hysky.skyblocker.utils.render.GuiHelper; import de.hysky.skyblocker.utils.render.gui.AbstractCustomHypixelGUI; import it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2DoubleMap; @@ -26,7 +26,7 @@ import java.util.function.Supplier; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.input.KeyEvent; @@ -41,7 +41,7 @@ import net.minecraft.util.CommonColors; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -101,7 +101,7 @@ protected void init() { resetFiltersButton.setTooltip(Tooltip.create(Component.literal("Reset Filters"))); resetFiltersButton.setTooltipDelay(Duration.ofMillis(500)); - addRenderableWidget(new Button.Builder(Component.literal("<"), button -> this.clickSlot(BACK_BUTTON_SLOT)) + addRenderableWidget(new Button.Builder(Component.literal("<"), _ -> this.clickSlot(BACK_BUTTON_SLOT)) .pos(leftPos + 98, topPos + 4) .size(12, 12) .build()); @@ -129,62 +129,63 @@ private void onResetPressed(Button buttonWidget) { } @Override - protected void renderBg(GuiGraphics context, float delta, int mouseX, int mouseY) { - context.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, 256, 256); + public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractBackground(graphics, mouseX, mouseY, a); + graphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, 256, 256); } @Override - public void render(GuiGraphics context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); + public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractRenderState(graphics, mouseX, mouseY, a); for (CategoryTabWidget categoryTabWidget : categoryTabWidgets) { - categoryTabWidget.render(context, mouseX, mouseY, delta); + categoryTabWidget.extractRenderState(graphics, mouseX, mouseY, a); } if (isWaitingForServer) { String waiting = "Waiting for server..."; - context.drawString(font, waiting, this.width - font.width(waiting) - 5, this.height - font.lineHeight - 2, CommonColors.WHITE, true); + graphics.text(font, waiting, this.width - font.width(waiting) - 5, this.height - font.lineHeight - 2, CommonColors.WHITE, true); } - Matrix3x2fStack matrices = context.pose(); + Matrix3x2fStack matrices = graphics.pose(); matrices.pushMatrix(); matrices.translate(leftPos, topPos); // Search - context.enableScissor(7, 4, 97, 16); - context.drawString(font, Component.literal(search).withStyle(Style.EMPTY.withUnderlined(onSearchField(mouseX, mouseY))), 9, 6, CommonColors.WHITE, true); - context.disableScissor(); + graphics.enableScissor(7, 4, 97, 16); + graphics.text(font, Component.literal(search).withStyle(Style.EMPTY.withUnderlined(onSearchField(mouseX, mouseY))), 9, 6, CommonColors.WHITE, true); + graphics.disableScissor(); // Scrollbar if (prevPageVisible) { if (onScrollbarTop(mouseX, mouseY)) - context.blitSprite(RenderPipelines.GUI_TEXTURED, UP_ARROW.get(), 159, 13, 6, 3); - else context.blitSprite(RenderPipelines.GUI_TEXTURED, UP_ARROW.get(), 159, 13, 6, 3, ARGB.color(137, 137, 137)); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, UP_ARROW.get(), 159, 13, 6, 3); + else graphics.blitSprite(RenderPipelines.GUI_TEXTURED, UP_ARROW.get(), 159, 13, 6, 3, ARGB.color(137, 137, 137)); } if (nextPageVisible) { if (onScrollbarBottom(mouseX, mouseY)) - context.blitSprite(RenderPipelines.GUI_TEXTURED, DOWN_ARROW.get(), 159, 72, 6, 3); - else context.blitSprite(RenderPipelines.GUI_TEXTURED, DOWN_ARROW.get(), 159, 72, 6, 3, ARGB.color(137, 137, 137)); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, DOWN_ARROW.get(), 159, 72, 6, 3); + else graphics.blitSprite(RenderPipelines.GUI_TEXTURED, DOWN_ARROW.get(), 159, 72, 6, 3, ARGB.color(137, 137, 137)); } - context.drawString(font, String.format("%d/%d", currentPage, totalPages), 111, 6, CommonColors.GRAY, false); + graphics.text(font, String.format("%d/%d", currentPage, totalPages), 111, 6, CommonColors.GRAY, false); if (totalPages <= 1) - context.blitSprite(RenderPipelines.GUI_TEXTURED, SCROLLER_TEXTURE, 156, 18, 12, 15); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, SCROLLER_TEXTURE, 156, 18, 12, 15); else - context.blitSprite(RenderPipelines.GUI_TEXTURED, SCROLLER_TEXTURE, 156, (int) (18 + (float) (Math.min(currentPage, totalPages) - 1) / (totalPages - 1) * 37), 12, 15); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, SCROLLER_TEXTURE, 156, (int) (18 + (float) (Math.min(currentPage, totalPages) - 1) / (totalPages - 1) * 37), 12, 15); matrices.popMatrix(); - this.renderTooltip(context, mouseX, mouseY); + this.extractTooltip(graphics, mouseX, mouseY); } @Override - protected void renderSlot(GuiGraphics context, Slot slot, int mouseX, int mouseY) { + protected void extractSlot(GuiGraphicsExtractor graphics, Slot slot, int mouseX, int mouseY) { if (SkyblockerConfigManager.get().uiAndVisuals.fancyAuctionHouse.highlightCheapBIN && slot.hasItem() && isSlotHighlighted.getOrDefault(slot.index, false)) { - HudHelper.drawBorder(context, slot.x, slot.y, 16, 16, new Color(0, 255, 0, 100).getRGB()); + GuiHelper.border(graphics, slot.x, slot.y, 16, 16, new Color(0, 255, 0, 100).getRGB()); } - super.renderSlot(context, slot, mouseX, mouseY); + super.extractSlot(graphics, slot, mouseX, mouseY); } @Override - protected void slotClicked(Slot slot, int slotId, int button, ClickType actionType) { + protected void slotClicked(Slot slot, int slotId, int button, ContainerInput actionType) { if (slotId >= menu.getRowCount() * 9) return; super.slotClicked(slot, slotId, button, actionType); } @@ -362,16 +363,16 @@ protected ScaledTextButtonWidget(int x, int y, int width, int height, Component // Code taken mostly from YACL by isxander. Love you <3 @Override - public void renderContents(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) { - this.renderDefaultSprite(context); + public void extractContents(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + this.extractDefaultSprite(graphics); Font font = Minecraft.getInstance().font; - Matrix3x2fStack matrices = context.pose(); + Matrix3x2fStack matrices = graphics.pose(); float textScale = 2.f; matrices.pushMatrix(); matrices.translate(((this.getX() + this.width / 2f) - font.width(getMessage()) * textScale / 2) + 1, (float) this.getY() + (this.height - font.lineHeight * textScale) / 2f - 1); matrices.scale(textScale, textScale); - context.drawString(font, getMessage(), 0, 0, CommonColors.WHITE | Mth.ceil(this.alpha * 255.0F) << 24, true); + graphics.text(font, getMessage(), 0, 0, CommonColors.WHITE | Mth.ceil(this.alpha * 255.0F) << 24, true); matrices.popMatrix(); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionViewScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionViewScreen.java index f1738dabd2..474e5ac8dc 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionViewScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionViewScreen.java @@ -12,7 +12,7 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.PopupScreen; import net.minecraft.client.gui.components.StringWidget; @@ -28,7 +28,7 @@ import net.minecraft.resources.Identifier; import net.minecraft.util.CommonColors; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import org.jspecify.annotations.Nullable; @@ -74,7 +74,7 @@ protected void init() { infoTextWidget = new StringWidget(Component.literal("Can't Afford"), font).setMaxWidth(imageWidth - 10, StringWidget.TextOverflow.SCROLLING); verticalLayout.addChild(infoTextWidget); - buyButton = Button.builder(isBinAuction ? Component.translatable("skyblocker.fancyAuctionHouse.buy") : Component.translatable("skyblocker.fancyAuctionHouse.bid"), button -> { + buyButton = Button.builder(isBinAuction ? Component.translatable("skyblocker.fancyAuctionHouse.buy") : Component.translatable("skyblocker.fancyAuctionHouse.bid"), _ -> { if (buySlotID == -1) return; clickSlot(buySlotID); }).size(60, 15).build(); @@ -82,7 +82,7 @@ protected void init() { verticalLayout.visitWidgets(this::addRenderableWidget); updateLayout(); - Button backButton = new Button.Builder(Component.literal("<"), button -> this.clickSlot(BACK_BUTTON_SLOT)) + Button backButton = new Button.Builder(Component.literal("<"), _ -> this.clickSlot(BACK_BUTTON_SLOT)) .pos(leftPos + imageWidth - 16, topPos + 4) .size(12, 12) .tooltip(Tooltip.create(Component.literal("or press ESC!"))) @@ -142,25 +142,26 @@ private void updateLayout() { } @Override - protected void renderBg(GuiGraphics context, float delta, int mouseX, int mouseY) { - context.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND_TEXTURE, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, 256, 256); + public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractBackground(graphics, mouseX, mouseY, a); + graphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND_TEXTURE, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, 256, 256); } @Override - public void render(GuiGraphics context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); + public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractRenderState(graphics, mouseX, mouseY, a); - if (isWaitingForServer) context.drawString(font, "Waiting...", 0, 0, CommonColors.WHITE, true); + if (isWaitingForServer) graphics.text(font, "Waiting...", 0, 0, CommonColors.WHITE, true); - Matrix3x2fStack matrices = context.pose(); + Matrix3x2fStack matrices = graphics.pose(); matrices.pushMatrix(); matrices.translate(leftPos + 77, topPos + 14); matrices.scale(1.375f, 1.375f); //matrices.translate(0, 0, 100f); ItemStack stack = menu.getSlot(13).getItem(); - context.renderItem(stack, 0, 0); - context.renderItemDecorations(font, stack, 0, 0); + graphics.item(stack, 0, 0); + graphics.itemDecorations(font, stack, 0, 0); matrices.popMatrix(); if (!isBinAuction && buyState != BuyState.COLLECT_AUCTION) { @@ -171,14 +172,14 @@ public void render(GuiGraphics context, int mouseX, int mouseY, float delta) { } } - renderTooltip(context, mouseX, mouseY); + extractTooltip(graphics, mouseX, mouseY); } @Override - protected void renderTooltip(GuiGraphics context, int x, int y) { - super.renderTooltip(context, x, y); + protected void extractTooltip(GuiGraphicsExtractor graphics, int x, int y) { + super.extractTooltip(graphics, x, y); if (x > this.leftPos + 75 && x < this.leftPos + 75 + 26 && y > this.topPos + 13 && y < this.topPos + 13 + 26) { - context.setComponentTooltipForNextFrame(this.font, this.getTooltipFromContainerItem(menu.getSlot(13).getItem()), x, y); + graphics.setComponentTooltipForNextFrame(this.font, this.getTooltipFromContainerItem(menu.getSlot(13).getItem()), x, y); } } @@ -281,13 +282,13 @@ public PopupScreen getConfirmPurchasePopup(Component title) { // This really shouldn't be possible to be null in its ACTUAL use case. //noinspection DataFlowIssue return new PopupScreen.Builder(this, title) - .addButton(Component.translatable("text.skyblocker.confirm"), popupScreen -> this.minecraft.gameMode.handleInventoryMouseClick(this.minecraft.player.containerMenu.containerId, 11, 0, ClickType.PICKUP, minecraft.player)) + .addButton(Component.translatable("text.skyblocker.confirm"), _ -> this.minecraft.gameMode.handleContainerInput(this.minecraft.player.containerMenu.containerId, 11, 0, ContainerInput.PICKUP, minecraft.player)) .addButton(Component.translatable("gui.cancel"), PopupScreen::onClose) - .setMessage((isBinAuction ? Component.translatable("skyblocker.fancyAuctionHouse.price") : Component.translatable("skyblocker.fancyAuctionHouse.newBid")).append(" ").append(priceText)) + .addMessage((isBinAuction ? Component.translatable("skyblocker.fancyAuctionHouse.price") : Component.translatable("skyblocker.fancyAuctionHouse.newBid")).append(" ").append(priceText)) .onClose(() -> { // This really shouldn't be possible to be null in its ACTUAL use case. //noinspection DataFlowIssue - this.minecraft.gameMode.handleInventoryMouseClick(this.minecraft.player.containerMenu.containerId, 15, 0, ClickType.PICKUP, minecraft.player); + this.minecraft.gameMode.handleContainerInput(this.minecraft.player.containerMenu.containerId, 15, 0, ContainerInput.PICKUP, minecraft.player); }) .build(); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/CopyUnderbidPrice.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/CopyUnderbidPrice.java index 2f3ae4d8c6..41b16b0db4 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/CopyUnderbidPrice.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/CopyUnderbidPrice.java @@ -66,8 +66,8 @@ public void markDirty() { if (client.player != null) { Component priceText = Component.literal(Formatters.INTEGER_NUMBERS.format(underbid)).withStyle(ChatFormatting.GOLD); - client.player.displayClientMessage(Constants.PREFIX.get() - .append(Component.translatable("skyblocker.copyUnderbidPrice.copied", priceText).withStyle(ChatFormatting.GRAY)), false); + client.player.sendSystemMessage(Constants.PREFIX.get() + .append(Component.translatable("skyblocker.copyUnderbidPrice.copied", priceText).withStyle(ChatFormatting.GRAY))); } copied = true; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java index c313b00bdf..b68794e587 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java @@ -3,10 +3,10 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.calculators.SignCalculator; import de.hysky.skyblocker.utils.render.gui.AbstractPopupScreen; +import de.hysky.skyblocker.utils.render.gui.FilteredEditBox; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.StringWidget; import net.minecraft.client.gui.layouts.FrameLayout; import net.minecraft.client.gui.layouts.LinearLayout; @@ -22,7 +22,7 @@ public class EditBidPopup extends AbstractPopupScreen { private final boolean signFront; - private EditBox textFieldWidget; + private FilteredEditBox textFieldWidget; private boolean packetSent = false; @@ -56,11 +56,11 @@ protected void init() { } @Override - public void renderBackground(GuiGraphics context, int mouseX, int mouseY, float delta) { - super.renderBackground(context, mouseX, mouseY, delta); - drawPopupBackground(context, layout.getX(), layout.getY(), layout.getWidth(), layout.getHeight()); + public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractBackground(graphics, mouseX, mouseY, a); + extractPopupBackground(graphics, layout.getX(), layout.getY(), layout.getWidth(), layout.getHeight()); if (SkyblockerConfigManager.get().uiAndVisuals.inputCalculator.enabled) { - SignCalculator.renderCalculator(context, textFieldWidget.getValue(), context.guiWidth() / 2, textFieldWidget.getY() - 8); + SignCalculator.extractCalculator(graphics, textFieldWidget.getValue(), graphics.guiWidth() / 2, textFieldWidget.getY() - 8); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/CategoryTabWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/CategoryTabWidget.java index d96a6cff7c..7c3fcddc9a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/CategoryTabWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/CategoryTabWidget.java @@ -3,7 +3,7 @@ import de.hysky.skyblocker.skyblock.auction.SlotClickHandler; import de.hysky.skyblocker.utils.render.gui.SideTabButtonWidget; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.world.item.Item.TooltipContext; import net.minecraft.world.item.ItemStack; @@ -19,11 +19,11 @@ public CategoryTabWidget(ItemStack icon, SlotClickHandler slotClick) { } @Override - public void renderContents(GuiGraphics context, int mouseX, int mouseY, float delta) { - super.renderContents(context, mouseX, mouseY, delta); + public void extractContents(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractContents(graphics, mouseX, mouseY, a); if (isMouseOver(mouseX, mouseY)) { - context.setComponentTooltipForNextFrame(Minecraft.getInstance().font, icon.getTooltipLines(TooltipContext.EMPTY, Minecraft.getInstance().player, TooltipFlag.NORMAL), mouseX, mouseY); + graphics.setComponentTooltipForNextFrame(Minecraft.getInstance().font, icon.getTooltipLines(TooltipContext.EMPTY, Minecraft.getInstance().player, TooltipFlag.NORMAL), mouseX, mouseY); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/RarityWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/RarityWidget.java index 190d3ae9e7..c27aac6aff 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/RarityWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/RarityWidget.java @@ -7,7 +7,7 @@ import java.util.Locale; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.input.MouseButtonEvent; @@ -34,15 +34,15 @@ public RarityWidget(int x, int y, SlotClickHandler onClick) { } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delta) { - Matrix3x2fStack matrices = context.pose(); + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + Matrix3x2fStack matrices = graphics.pose(); matrices.pushMatrix(); matrices.translate(getX(), getY()); boolean onLeftArrow = isOnLeftArrow(mouseX); boolean onRightArrow = isOnRightArrow(mouseX); - context.blitSprite(RenderPipelines.GUI_TEXTURED, BACKGROUND, 6, 0, 36, 11); - context.blitSprite(RenderPipelines.GUI_TEXTURED, onLeftArrow ? LEFT_HOVER_TEXTURE : LEFT_TEXTURE, 0, 0, 6, 11); - context.blitSprite(RenderPipelines.GUI_TEXTURED, onRightArrow ? RIGHT_HOVER_TEXTURE : RIGHT_TEXTURE, 42, 0, 6, 11); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, BACKGROUND, 6, 0, 36, 11); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, onLeftArrow ? LEFT_HOVER_TEXTURE : LEFT_TEXTURE, 0, 0, 6, 11); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, onRightArrow ? RIGHT_HOVER_TEXTURE : RIGHT_TEXTURE, 42, 0, 6, 11); // Text Font textRenderer = Minecraft.getInstance().font; @@ -52,14 +52,14 @@ protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float d matrices.pushMatrix(); matrices.translate(0f, 5.5f); matrices.scale(scale, scale); - context.drawCenteredString(textRenderer, current, (int) (24 / scale), -textRenderer.lineHeight / 2, color); + graphics.centeredText(textRenderer, current, (int) (24 / scale), -textRenderer.lineHeight / 2, color); matrices.popMatrix(); } else { - context.drawCenteredString(textRenderer, current, 24, 2, color); + graphics.centeredText(textRenderer, current, 24, 2, color); } matrices.popMatrix(); - if (!onLeftArrow && !onRightArrow && isHovered()) context.setComponentTooltipForNextFrame(textRenderer, tooltip, mouseX, mouseY); + if (!onLeftArrow && !onRightArrow && isHovered()) graphics.setComponentTooltipForNextFrame(textRenderer, tooltip, mouseX, mouseY); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/SliderWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/SliderWidget.java index 8cae80eb42..d057f9b346 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/SliderWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/SliderWidget.java @@ -1,7 +1,7 @@ package de.hysky.skyblocker.skyblock.auction.widgets; import de.hysky.skyblocker.skyblock.auction.SlotClickHandler; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.input.MouseButtonEvent; @@ -37,7 +37,7 @@ public SliderWidget(int x, int y, int width, int height, Component message, Slot } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delta) { + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float delta) { if (posProgress < current.getOffset()) { posProgress += delta * 5; if (posProgress > current.getOffset()) posProgress = current.getOffset(); @@ -47,8 +47,8 @@ protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float d } - context.pose().pushMatrix(); - context.pose().translate(getX(), getY()); + graphics.pose().pushMatrix(); + graphics.pose().translate(getX(), getY()); int x = current.isVertical() ? 0 : Math.round(posProgress); int y = current.isVertical() ? Math.round(posProgress) : 0; @@ -56,13 +56,13 @@ protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float d int optionWidth = current.getOptionSize()[0]; int optionHeight = current.getOptionSize()[1]; - context.blitSprite(RenderPipelines.GUI_TEXTURED, current.getBackTexture(), 0, 0, getWidth(), getHeight()); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, current.getBackTexture(), 0, 0, getWidth(), getHeight()); if (isHovered()) { - context.blitSprite(RenderPipelines.GUI_TEXTURED, current.getHoverTexture(), x, y, optionWidth, optionHeight); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, current.getHoverTexture(), x, y, optionWidth, optionHeight); } else { - context.blitSprite(RenderPipelines.GUI_TEXTURED, current.getOptionTexture(), x, y, optionWidth, optionHeight); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, current.getOptionTexture(), x, y, optionWidth, optionHeight); } - context.pose().popMatrix(); + graphics.pose().popMatrix(); } @Override diff --git a/src/main/java/de/hysky/skyblocker/skyblock/barn/CallTrevor.java b/src/main/java/de/hysky/skyblocker/skyblock/barn/CallTrevor.java index f81504d22b..093ddb9f5a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/barn/CallTrevor.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/barn/CallTrevor.java @@ -32,7 +32,7 @@ protected boolean onMatch(Component message, Matcher matcher) { style.withClickEvent(new ClickEvent.RunCommand("/call trevor")) .withColor(ChatFormatting.AQUA) ); - player.displayClientMessage(callMessage, false); + player.sendSystemMessage(callMessage); return false; // We do not actually want to filter the message. } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/barn/GlowingMushrooms.java b/src/main/java/de/hysky/skyblocker/skyblock/barn/GlowingMushrooms.java index 311733d349..7c306add18 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/barn/GlowingMushrooms.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/barn/GlowingMushrooms.java @@ -7,7 +7,7 @@ import de.hysky.skyblocker.utils.ColorUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.RenderHelper; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import de.hysky.skyblocker.utils.scheduler.Scheduler; import de.hysky.skyblocker.utils.waypoint.SeenWaypoint; @@ -33,12 +33,12 @@ public class GlowingMushrooms { public static void init() { ParticleEvents.FROM_SERVER.register(GlowingMushrooms::onParticle); Scheduler.INSTANCE.scheduleCyclic(GlowingMushrooms::update, 1); - WorldRenderExtractionCallback.EVENT.register(GlowingMushrooms::extractRendering); - AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> { + LevelRenderExtractionCallback.EVENT.register(GlowingMushrooms::extractRendering); + AttackBlockCallback.EVENT.register((_, _, _, pos, _) -> { if (shouldProcess()) glowingMushrooms.remove(pos); return InteractionResult.PASS; }); - ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> reset()); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); } public static void onParticle(ClientboundLevelParticlesPacket packet) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/barn/TreasureHunter.java b/src/main/java/de/hysky/skyblocker/skyblock/barn/TreasureHunter.java index ded426762f..78443b843d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/barn/TreasureHunter.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/barn/TreasureHunter.java @@ -33,7 +33,7 @@ public boolean onMatch(Component message, Matcher matcher) { String hint = matcher.group(1); String location = locations.get(hint); if (location == null) return false; - client.player.displayClientMessage(Component.nullToEmpty("§e[NPC] Treasure Hunter§f: Go mine around " + location), false); + client.player.sendSystemMessage(Component.nullToEmpty("§e[NPC] Treasure Hunter§f: Go mine around " + location)); requestWaypoint(location); return true; } @@ -45,7 +45,7 @@ private static void requestWaypoint(String location) { .withClickEvent(new ClickEvent.RunCommand(command.trim())) ) ); - Minecraft.getInstance().player.displayClientMessage(requestMessage, false); + Minecraft.getInstance().player.sendSystemMessage(requestMessage); } static { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/bazaar/BazaarQuickQuantities.java b/src/main/java/de/hysky/skyblocker/skyblock/bazaar/BazaarQuickQuantities.java index 043ff893d9..75301a718b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/bazaar/BazaarQuickQuantities.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/bazaar/BazaarQuickQuantities.java @@ -21,11 +21,11 @@ public static Button[] getButtons(int width, String[] messages) { int y = 45; buttons[0] = Button.builder(Component.nullToEmpty(String.valueOf(config.slot1Quantity)), - button -> onButtonPressed(messages, config.slot1Quantity)).bounds(x, y + 20, 50, 20).build(); + _ -> onButtonPressed(messages, config.slot1Quantity)).bounds(x, y + 20, 50, 20).build(); buttons[1] = Button.builder(Component.nullToEmpty(String.valueOf(config.slot2Quantity)), - button -> onButtonPressed(messages, config.slot2Quantity)).bounds(x, y + 40, 50, 20).build(); + _ -> onButtonPressed(messages, config.slot2Quantity)).bounds(x, y + 40, 50, 20).build(); buttons[2] = Button.builder(Component.nullToEmpty(String.valueOf(config.slot3Quantity)), - button -> onButtonPressed(messages, config.slot3Quantity)).bounds(x, y + 60, 50, 20).build(); + _ -> onButtonPressed(messages, config.slot3Quantity)).bounds(x, y + 60, 50, 20).build(); String clipboard = client.keyboardHandler.getClipboard(); if (clipboard.length() <= 5 && NumberUtils.isCreatable(clipboard)) { // Only show option if clipboard is numeric @@ -33,7 +33,7 @@ public static Button[] getButtons(int width, String[] messages) { text.withStyle(style -> style.withColor(ChatFormatting.AQUA)); buttons[3] = Button.builder(text, - button -> onButtonPressed(messages, clipboard)).bounds(x, y + 80, 50, 20).build(); + _ -> onButtonPressed(messages, clipboard)).bounds(x, y + 80, 50, 20).build(); } return buttons; } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/calculators/CalculatorCommand.java b/src/main/java/de/hysky/skyblocker/skyblock/calculators/CalculatorCommand.java index 38fcccaaef..705577e5be 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/calculators/CalculatorCommand.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/calculators/CalculatorCommand.java @@ -17,8 +17,8 @@ import net.minecraft.network.chat.MutableComponent; import static com.mojang.brigadier.arguments.StringArgumentType.getString; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; public class CalculatorCommand { private static final Minecraft CLIENT = Minecraft.getInstance(); @@ -51,7 +51,7 @@ private static int doCalculation(String calculation) { return 0; } - CLIENT.player.displayClientMessage(text, false); + CLIENT.player.sendSystemMessage(text); return Command.SINGLE_SUCCESS; } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/calculators/SignCalculator.java b/src/main/java/de/hysky/skyblocker/skyblock/calculators/SignCalculator.java index ef68053a12..e75317cef3 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/calculators/SignCalculator.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/calculators/SignCalculator.java @@ -5,7 +5,7 @@ import de.hysky.skyblocker.utils.Formatters; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import org.jetbrains.annotations.VisibleForTesting; @@ -16,7 +16,7 @@ public class SignCalculator { private static double output; private static Component error; - public static void renderCalculator(GuiGraphics context, String message, int renderX, int renderY) { + public static void extractCalculator(GuiGraphicsExtractor graphics, String message, int renderX, int renderY) { if (SkyblockerConfigManager.get().uiAndVisuals.inputCalculator.requiresEquals && !message.startsWith("=")) { output = -1; error = null; @@ -28,7 +28,7 @@ public static void renderCalculator(GuiGraphics context, String message, int ren } calculate(message); - render(context, message, renderX, renderY); + extract(graphics, message, renderX, renderY); } @VisibleForTesting @@ -60,7 +60,7 @@ public static String getNewValue(boolean isPrice) { return Long.toString(Math.round(output)); } - private static void render(GuiGraphics context, String input, int renderX, int renderY) { + private static void extract(GuiGraphicsExtractor graphics, String input, int renderX, int renderY) { Component text; if (output == -1) { text = error != null ? error : Component.translatable("skyblocker.config.uiAndVisuals.inputCalculator.invalidEquation").withStyle(ChatFormatting.RED); @@ -68,6 +68,6 @@ private static void render(GuiGraphics context, String input, int renderX, int r text = Component.literal(input + " = " + Formatters.DOUBLE_NUMBERS.format(output)).withStyle(ChatFormatting.GREEN); } - context.drawCenteredString(CLIENT.font, text, renderX, renderY, 0xFFFFFFFF); + graphics.centeredText(CLIENT.font, text, renderX, renderY, 0xFFFFFFFF); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/carnival/ZombieShootout.java b/src/main/java/de/hysky/skyblocker/skyblock/carnival/ZombieShootout.java index 463fb3e906..2a0eb34988 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/carnival/ZombieShootout.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/carnival/ZombieShootout.java @@ -4,7 +4,7 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.crimson.dojo.DisciplineTestHelper; import de.hysky.skyblocker.skyblock.entity.MobGlow; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; @@ -39,7 +39,7 @@ public class ZombieShootout { @Init public static void init() { - WorldRenderExtractionCallback.EVENT.register(ZombieShootout::extractRendering); + LevelRenderExtractionCallback.EVENT.register(ZombieShootout::extractRendering); } private static void extractRendering(PrimitiveCollector collector) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatPositionShare.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatPositionShare.java index d6a9a335e0..4e28f671c3 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatPositionShare.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatPositionShare.java @@ -6,8 +6,8 @@ import de.hysky.skyblocker.utils.Constants; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.MessageScheduler; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.command.v2.ClientCommands; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.ChatFormatting; @@ -34,12 +34,12 @@ public class ChatPositionShare { @Init public static void init() { - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> { dispatcher.register( - ClientCommandManager.literal("skyblocker").then(ClientCommandManager.literal("sharePosition").executes(context -> sharePlayerPosition(context.getSource()))) + ClientCommands.literal("skyblocker").then(ClientCommands.literal("sharePosition").executes(context -> sharePlayerPosition(context.getSource()))) ); dispatcher.register( - ClientCommandManager.literal("skyblocker").then(ClientCommandManager.literal("shareCoords").executes(context -> sharePlayerPosition(context.getSource()))) + ClientCommands.literal("skyblocker").then(ClientCommands.literal("shareCoords").executes(context -> sharePlayerPosition(context.getSource()))) ); }); ClientReceiveMessageEvents.ALLOW_GAME.register(ChatPositionShare::onMessage); @@ -91,6 +91,6 @@ private static void requestWaypoint(String x, String y, String z, String area) { if (!area.isEmpty()) { requestMessage = requestMessage.append(" at ").append(Component.literal(area).withStyle(ChatFormatting.AQUA)); } - Minecraft.getInstance().player.displayClientMessage(requestMessage, false); + Minecraft.getInstance().player.sendSystemMessage(requestMessage); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRule.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRule.java index 34f67d54b0..7374f490a2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRule.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRule.java @@ -258,11 +258,11 @@ private void compilePattern(String filterText) { try { this.pattern = Pattern.compile(filterText); - } catch (PatternSyntaxException ex) { + } catch (PatternSyntaxException _) { this.enabled = false; Minecraft client = Minecraft.getInstance(); if (client.player == null) return; - client.player.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.config.chat.chatRules.invalidRegex", this.name)), false); + client.player.sendSystemMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.config.chat.chatRules.invalidRegex", this.name))); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRuleConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRuleConfigScreen.java index 2e973bd9f1..d5a7586c60 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRuleConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRuleConfigScreen.java @@ -8,8 +8,9 @@ import de.hysky.skyblocker.utils.render.gui.ToggleableLayoutWidget; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.AbstractContainerWidget; +import net.minecraft.client.gui.components.AbstractScrollArea; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.CycleButton; @@ -82,6 +83,7 @@ public class ChatRuleConfigScreen extends Screen { private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this); private final GridLayout content = new GridLayout().columnSpacing(GRID_SPACING); + @SuppressWarnings("rawtypes") private CycleButton soundButton; public ChatRuleConfigScreen(Screen parent, int chatRuleIndex) { @@ -95,7 +97,7 @@ public ChatRuleConfigScreen(Screen parent, int chatRuleIndex) { protected void init() { Objects.requireNonNull(minecraft); layout.addToHeader(new StringWidget(title, font)); - layout.addToFooter(Button.builder(CommonComponents.GUI_DONE, b -> onClose()).build()); + layout.addToFooter(Button.builder(CommonComponents.GUI_DONE, _ -> onClose()).build()); layout.addToContents(new ContentContainer()); content.defaultCellSetting().alignVerticallyMiddle().alignHorizontallyCenter().paddingTop(GRID_SPACING); // Have to separate them due to the toggleable layouts, did not think about that when I made them @@ -122,17 +124,17 @@ protected void init() { // Filter settings LinearLayout filtersRow1 = contentAdder.addChild(LinearLayout.horizontal().spacing(GRID_SPACING), 3); filtersRow1.addChild(CycleButton.booleanBuilder(YES_TEXT, NO_TEXT, chatRule.getRegex()) - .withTooltip(b -> Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.regex.@Tooltip"))) - .create(0, 0, getWidth(1.5f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.regex"), (button, value) -> chatRule.setRegex(value))); + .withTooltip(_ -> Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.regex.@Tooltip"))) + .create(0, 0, getWidth(1.5f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.regex"), (_, value) -> chatRule.setRegex(value))); filtersRow1.addChild(CycleButton.booleanBuilder(YES_TEXT, NO_TEXT, chatRule.getIgnoreCase()) - .withTooltip(b -> Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.ignoreCase.@Tooltip"))) - .create(0, 0, getWidth(1.5f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.ignoreCase"), (button, value) -> chatRule.setIgnoreCase(value))); + .withTooltip(_ -> Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.ignoreCase.@Tooltip"))) + .create(0, 0, getWidth(1.5f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.ignoreCase"), (_, value) -> chatRule.setIgnoreCase(value))); LinearLayout filtersRow2 = contentAdder.addChild(LinearLayout.horizontal().spacing(GRID_SPACING), 3); filtersRow2.addChild(CycleButton.booleanBuilder(YES_TEXT, NO_TEXT, chatRule.getPartialMatch()) - .withTooltip(b -> Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.partialMatch.@Tooltip"))) - .create(0, 0, getWidth(1.5f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.partialMatch"), (button, value) -> chatRule.setPartialMatch(value))); + .withTooltip(_ -> Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.partialMatch.@Tooltip"))) + .create(0, 0, getWidth(1.5f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.partialMatch"), (_, value) -> chatRule.setPartialMatch(value))); filtersRow2.addChild(Button.builder(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.locations"), - widget -> minecraft.setScreen(new ChatRuleLocationConfigScreen(this, chatRule))) + _ -> minecraft.setScreen(new ChatRuleLocationConfigScreen(this, chatRule))) .tooltip(Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.locations.@Tooltip"))) .width(getWidth(1.5f)) .build()); @@ -144,8 +146,8 @@ protected void init() { LinearLayout buttons = contentAdder.addChild(LinearLayout.horizontal().spacing(GRID_SPACING), 3); buttons.addChild(CycleButton.booleanBuilder(YES_TEXT, NO_TEXT, chatRule.getHideMessage()) - .withTooltip(b -> Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.hideMessage.@Tooltip"))) - .create(0, 0, getWidth(1.5f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.hideMessage"), (button, value) -> { + .withTooltip(_ -> Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.hideMessage.@Tooltip"))) + .create(0, 0, getWidth(1.5f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.hideMessage"), (_, value) -> { chatRule.setHideMessage(value); recreateLayout(); })); @@ -163,8 +165,7 @@ protected void init() { // using an optional since it doesn't allow null values. soundButton = CycleButton.builder(opt -> soundNames.get(opt.orElse(null)), Optional.ofNullable(chatRule.getCustomSound())) .withValues(() -> true, displayedValues, availableValues) - - .create(0, 0, getWidth(1.3f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.sounds"), (button, value) -> { + .create(0, 0, getWidth(1.3f), 20, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.sounds"), (_, value) -> { chatRule.setCustomSound(value.orElse(null)); value.ifPresent(soundEvent -> minecraft.getSoundManager().play(SimpleSoundInstance.forUI(soundEvent, 1.0F))); }); @@ -357,8 +358,8 @@ private ToastIconPreview(EditBox input) { } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) { - context.renderFakeItem(stack, getX(), getY()); + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + graphics.fakeItem(stack, getX(), getY()); } @Override @@ -388,8 +389,8 @@ private SoundSearchMenu() { } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) { - context.blitSprite(RenderPipelines.GUI_TEXTURED, SEARCH_ICON_TEXTURE, this.getX(), this.getY(), this.getWidth(), this.getHeight()); + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, SEARCH_ICON_TEXTURE, this.getX(), this.getY(), this.getWidth(), this.getHeight()); } @Override @@ -418,7 +419,7 @@ private class ContentContainer extends AbstractContainerWidget implements Layout private final List children = new ArrayList<>(); private ContentContainer() { - super(0, 0, 0, 0, Component.empty()); + super(0, 0, 0, 0, Component.empty(), AbstractScrollArea.defaultSettings(8)); } @Override @@ -437,15 +438,15 @@ protected double scrollRate() { } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) { - context.enableScissor(this.getX(), this.getY(), this.getX() + this.width, this.getY() + this.height); + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + graphics.enableScissor(this.getX(), this.getY(), this.getX() + this.width, this.getY() + this.height); for (AbstractWidget clickableWidget : this.children) { - clickableWidget.render(context, mouseX, mouseY, deltaTicks); + clickableWidget.extractRenderState(graphics, mouseX, mouseY, a); } - context.disableScissor(); - this.renderScrollbar(context, mouseX, mouseY); + graphics.disableScissor(); + this.extractScrollbar(graphics, mouseX, mouseY); } @Override diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRuleLocationConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRuleLocationConfigScreen.java index 29ebe04a5f..6ae4cc9648 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRuleLocationConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRuleLocationConfigScreen.java @@ -28,9 +28,9 @@ public ChatRuleLocationConfigScreen(@Nullable Screen parent, ChatRule chatRule) @Override protected void init() { assert minecraft != null; - addRenderableOnly((context, mouseX, mouseY, delta) -> { - context.drawCenteredString(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.locationsConfigScreen").withStyle(ChatFormatting.BOLD), width / 2, (32 - minecraft.font.lineHeight) / 2, CommonColors.WHITE); - context.drawCenteredString(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.locationsConfigScreen.note"), width / 2, (38 - minecraft.font.lineHeight), CommonColors.WHITE); + addRenderableOnly((context, _, _, _) -> { + context.centeredText(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.locationsConfigScreen").withStyle(ChatFormatting.BOLD), width / 2, (32 - minecraft.font.lineHeight) / 2, CommonColors.WHITE); + context.centeredText(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleScreen.locationsConfigScreen.note"), width / 2, (38 - minecraft.font.lineHeight), CommonColors.WHITE); }); ItemTickList itemTickList = addRenderableWidget(new ItemTickList<>(minecraft, width, height - 107, 43, 24, enabledLocations, EnumSet.complementOf(EnumSet.of(Location.UNKNOWN)), true).init()); @@ -39,16 +39,16 @@ protected void init() { gridWidget.defaultCellSetting().paddingHorizontal(5).paddingVertical(2); GridLayout.RowHelper adder = gridWidget.createRowHelper(2); - adder.addChild(Button.builder(Component.translatable("text.skyblocker.reset"), button -> { + adder.addChild(Button.builder(Component.translatable("text.skyblocker.reset"), _ -> { enabledLocations.clear(); itemTickList.clearAndInit(); }).build()); - adder.addChild(Button.builder(Component.translatable("text.skyblocker.undo"), button -> { + adder.addChild(Button.builder(Component.translatable("text.skyblocker.undo"), _ -> { enabledLocations.clear(); enabledLocations.addAll(chatRule.getValidLocations()); itemTickList.clearAndInit(); }).build()); - adder.addChild(Button.builder(CommonComponents.GUI_DONE, button -> { + adder.addChild(Button.builder(CommonComponents.GUI_DONE, _ -> { saveFilters(); onClose(); }) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesConfigListWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesConfigListWidget.java index 234a3f7746..65e4dcd7c6 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesConfigListWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesConfigListWidget.java @@ -4,7 +4,7 @@ import java.awt.Color; import java.util.List; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.Tooltip; @@ -101,11 +101,11 @@ public List children() { } @Override - public void renderContent(GuiGraphics context, int mouseX, int mouseY, boolean hovered, float deltaTicks) { - context.drawCenteredString(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleName"), ChatRulesConfigListWidget.this.getWidth() / 2 - 100, this.getY() + 5, CommonColors.WHITE); - context.drawCenteredString(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleEnabled"), ChatRulesConfigListWidget.this.getWidth() / 2 - 10, this.getY() + 5, CommonColors.WHITE); - context.drawCenteredString(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.modify"), ChatRulesConfigListWidget.this.getWidth() / 2 + 77, this.getY() + 5, CommonColors.WHITE); - context.fill(getRowLeft(), getY() + 15, getRowRight(), getY() + 16, CommonColors.LIGHT_GRAY); + public void extractContent(GuiGraphicsExtractor graphics, int mouseX, int mouseY, boolean hovered, float a) { + graphics.centeredText(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleName"), ChatRulesConfigListWidget.this.getWidth() / 2 - 100, this.getY() + 5, CommonColors.WHITE); + graphics.centeredText(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.ruleEnabled"), ChatRulesConfigListWidget.this.getWidth() / 2 - 10, this.getY() + 5, CommonColors.WHITE); + graphics.centeredText(minecraft.font, Component.translatable("skyblocker.config.chat.chatRules.screen.modify"), ChatRulesConfigListWidget.this.getWidth() / 2 + 77, this.getY() + 5, CommonColors.WHITE); + graphics.fill(getRowLeft(), getY() + 15, getRowRight(), getY() + 16, CommonColors.LIGHT_GRAY); } } @@ -149,9 +149,9 @@ private ChatRuleEntry(int chatRuleIndex) { Button enabledButton = layout.addChild(Button.builder(enabledButtonText(), this::toggleEnabled).size(50, 20).build()); - Button openConfigButton = layout.addChild(Button.builder(Component.translatable("skyblocker.config.chat.chatRules.screen.editRule"), a -> minecraft.setScreen(new ChatRuleConfigScreen(screen, chatRuleIndex))).size(50, 20).tooltip(Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.editRule.@Tooltip"))).build()); + Button openConfigButton = layout.addChild(Button.builder(Component.translatable("skyblocker.config.chat.chatRules.screen.editRule"), _ -> minecraft.setScreen(new ChatRuleConfigScreen(screen, chatRuleIndex))).size(50, 20).tooltip(Tooltip.create(Component.translatable("skyblocker.config.chat.chatRules.screen.editRule.@Tooltip"))).build()); - Button deleteButton = layout.addChild(Button.builder(Component.translatable("selectServer.delete"), a -> + Button deleteButton = layout.addChild(Button.builder(Component.translatable("selectServer.delete"), _ -> minecraft.setScreen(new ConfirmScreen(this::deleteEntry, Component.translatable("skyblocker.config.chat.chatRules.screen.deleteQuestion"), Component.translatable("skyblocker.config.chat.chatRules.screen.deleteWarning", chatRule.getName()), Component.translatable("selectServer.deleteButton"), CommonComponents.GUI_CANCEL)) ).size(50, 20).build()); @@ -183,11 +183,11 @@ private void deleteEntry(boolean confirmedAction) { } @Override - public void renderContent(GuiGraphics context, int mouseX, int mouseY, boolean hovered, float deltaTicks) { + public void extractContent(GuiGraphicsExtractor graphics, int mouseX, int mouseY, boolean hovered, float a) { // Widgets - layout.visitWidgets((child) -> child.render(context, mouseX, mouseY, deltaTicks)); + layout.visitWidgets(child -> child.extractRenderState(graphics, mouseX, mouseY, a)); // Text - context.drawCenteredString(minecraft.font, chatRule.getName(), getX() + 60, this.getY() + 8, CommonColors.WHITE); + graphics.centeredText(minecraft.font, chatRule.getName(), getX() + 60, this.getY() + 8, CommonColors.WHITE); } @Override diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesConfigScreen.java index 577d3c84a9..2d096160ac 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesConfigScreen.java @@ -25,13 +25,13 @@ protected void init() { chatRulesConfigListWidget = layout.addToContents(new ChatRulesConfigListWidget(minecraft, this, width, layout.getContentHeight(), layout.getHeaderHeight())); LinearLayout footerLayout = layout.addToFooter(new LinearLayout(0, 0, LinearLayout.Orientation.HORIZONTAL)); footerLayout.defaultCellSetting().paddingHorizontal(5).paddingVertical(2); - footerLayout.addChild(Button.builder(CommonComponents.GUI_CANCEL, button -> { + footerLayout.addChild(Button.builder(CommonComponents.GUI_CANCEL, _ -> { if (minecraft != null) onClose(); }).build()); footerLayout.addChild(Button.builder(Component.translatable("skyblocker.config.chat.chatRules.screen.new"), - buttonNew -> chatRulesConfigListWidget.addRuleAfterSelected() + _ -> chatRulesConfigListWidget.addRuleAfterSelected() ).build()); - footerLayout.addChild(Button.builder(CommonComponents.GUI_DONE, button -> { + footerLayout.addChild(Button.builder(CommonComponents.GUI_DONE, _ -> { chatRulesConfigListWidget.saveRules(); if (minecraft != null) { onClose(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesHandler.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesHandler.java index 12ec8b1335..f38482826f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesHandler.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesHandler.java @@ -13,8 +13,8 @@ import de.hysky.skyblocker.utils.render.title.Title; import de.hysky.skyblocker.utils.render.title.TitleContainer; import de.hysky.skyblocker.utils.scheduler.Scheduler; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.command.v2.ClientCommands; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.ChatFormatting; @@ -40,11 +40,11 @@ public class ChatRulesHandler { @Init public static void init() { - ClientLifecycleEvents.CLIENT_STARTED.register(client -> CHAT_RULE_LIST.init()); + ClientLifecycleEvents.CLIENT_STARTED.register(_ -> CHAT_RULE_LIST.init()); ClientReceiveMessageEvents.ALLOW_GAME.register(ChatRulesHandler::checkMessage); - ClientCommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> - dispatcher.register(ClientCommandManager.literal(SkyblockerMod.NAMESPACE) - .then(ClientCommandManager.literal("chatRules") + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> + dispatcher.register(ClientCommands.literal(SkyblockerMod.NAMESPACE) + .then(ClientCommands.literal("chatRules") .executes( Scheduler.queueOpenScreenCommand(() -> new ChatRulesConfigScreen(null))) ))); @@ -85,7 +85,7 @@ private static boolean checkMessage(Component message, boolean overlay) { // Show in action bar if (rule.getActionBarMessage() != null && CLIENT.player != null) { - CLIENT.player.displayClientMessage(formatText(match.insertCaptureGroups(rule.getActionBarMessage())), true); + CLIENT.player.sendOverlayMessage(formatText(match.insertCaptureGroups(rule.getActionBarMessage()))); } if (rule.getToastMessage() != null) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ConfirmationPromptHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ConfirmationPromptHelper.java index 1f404fe551..b1bec34047 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ConfirmationPromptHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ConfirmationPromptHelper.java @@ -44,10 +44,10 @@ public class ConfirmationPromptHelper { @Init public static void init() { ClientReceiveMessageEvents.ALLOW_GAME.register(ConfirmationPromptHelper::onMessage); - ScreenEvents.AFTER_INIT.register((_client, screen, _scaledWidth, _scaledHeight) -> { + ScreenEvents.AFTER_INIT.register((_, screen, _, _) -> { //Don't check for the command being present in case the user opens the chat before the prompt is sent if (Utils.isOnSkyblock() && screen instanceof ChatScreen && SkyblockerConfigManager.get().chat.confirmationPromptHelper) { - ScreenMouseEvents.beforeMouseClick(screen).register((_screen1, click) -> { + ScreenMouseEvents.beforeMouseClick(screen).register((_, click) -> { if (hasCommand()) { Minecraft client = Minecraft.getInstance(); if (client.screen instanceof ChatScreen) { // Ignore clicks on other interactive elements @@ -67,7 +67,7 @@ public static void init() { }); } }); - ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> { + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> { command = null; commandFoundAt = 0; }); @@ -106,7 +106,7 @@ private static boolean onMessage(Component message, boolean overlay) { commandFoundAt = System.currentTimeMillis(); //Send feedback msg - Minecraft.getInstance().player.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.chat.confirmationPromptNotification")), false); + Minecraft.getInstance().player.sendSystemMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.chat.confirmationPromptNotification"))); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/SkyblockXpMessages.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/SkyblockXpMessages.java index 574724cfaa..26152470c9 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/SkyblockXpMessages.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/SkyblockXpMessages.java @@ -32,7 +32,7 @@ private static boolean onMessage(Component text, boolean overlay) { int hash = xpMessage.hashCode(); if (!RECENT_MESSAGES.contains(hash)) { - CLIENT.player.displayClientMessage(Constants.PREFIX.get().append(xpMessage), false); + CLIENT.player.sendSystemMessage(Constants.PREFIX.get().append(xpMessage)); RECENT_MESSAGES.add(hash); Scheduler.INSTANCE.schedule(() -> RECENT_MESSAGES.remove(hash), 20 * 10); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/filters/AutopetFilter.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/filters/AutopetFilter.java index 6292b4174a..00a8f7682b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/filters/AutopetFilter.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/filters/AutopetFilter.java @@ -16,10 +16,10 @@ public AutopetFilter() { @Override public boolean onMatch(Component _message, Matcher matcher) { if (SkyblockerConfigManager.get().chat.hideAutopet == ChatFilterResult.ACTION_BAR) { - Objects.requireNonNull(Minecraft.getInstance().player).displayClientMessage( + Objects.requireNonNull(Minecraft.getInstance().player).sendOverlayMessage( Component.literal( _message.getString().replace("VIEW RULE", "") - ), true); + )); } return true; } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java index d93a5f5367..ebdb0f345f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java @@ -13,7 +13,7 @@ import de.hysky.skyblocker.utils.Location; import de.hysky.skyblocker.utils.SkyblockTime; import de.hysky.skyblocker.utils.command.argumenttypes.EggTypeArgumentType; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import de.hysky.skyblocker.utils.scheduler.MessageScheduler; import de.hysky.skyblocker.utils.waypoint.Waypoint; @@ -47,8 +47,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; public class EggFinder { private static final Logger LOGGER = LoggerFactory.getLogger("Skyblocker Egg Finder"); @@ -63,10 +63,10 @@ public class EggFinder { @Init public static void init() { - ClientPlayConnectionEvents.JOIN.register((ignored, ignored2, ignored3) -> clearEggs()); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> clearEggs()); SkyblockEvents.LOCATION_CHANGE.register(EggFinder::handleLocationChange); ClientReceiveMessageEvents.ALLOW_GAME.register(EggFinder::onChatMessage); - WorldRenderExtractionCallback.EVENT.register(EggFinder::extractRendering); + LevelRenderExtractionCallback.EVENT.register(EggFinder::extractRendering); SkyblockTime.HOUR_CHANGE.register(hour -> { if (!isSpring) return; @@ -86,7 +86,7 @@ public static void init() { if (!isSpring) clearEggs(); }); - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> { dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("eggFinder").then(literal("shareLocation").then(argument("eggType", EggTypeArgumentType.eggType()) .executes(context -> { EggType eggType = context.getArgument("eggType", EggType.class); @@ -100,7 +100,7 @@ public static void init() { if (!Debug.debugEnabled()) return; dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("eggFinder").then(literal("resetFoundStatus") - .executes(context -> { + .executes(_ -> { for (EggType type : EggType.entries) { type.collected = false; if (type.egg != null) type.egg.setMissing(); @@ -109,7 +109,7 @@ public static void init() { })))); dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("eggFinder").then(literal("clearWaypoints") - .executes(context -> { + .executes(_ -> { clearEggs(); return Command.SINGLE_SUCCESS; })))); @@ -180,7 +180,7 @@ private static boolean onChatMessage(Component text, boolean overlay) { if (client.player == null || client.level == null) return true; List entities = client.level.getEntitiesOfClass(ArmorStand.class, AABB.ofSize(client.player.position(), 4f, 4f, 4f), - (entity) -> EggFinder.checkIfEgg(entity, eggType) + entity -> EggFinder.checkIfEgg(entity, eggType) ); if (entities.size() != 1) return true; @@ -244,12 +244,11 @@ public void onEggReceived() { public void sendEggMessage() { MutableComponent eggName = Component.translatable("skyblocker.helpers.hoppitysHunt.chocolateEgg", this.name).withColor(color); - Minecraft.getInstance().player.displayClientMessage( + Minecraft.getInstance().player.sendSystemMessage( Constants.PREFIX.get().append(Component.translatable("skyblocker.helpers.hoppitysHunt.newEggDiscovered", eggName, egg.pos.toShortString()) ).withStyle(style -> style.withClickEvent(new ClickEvent.RunCommand("/skyblocker eggFinder shareLocation " + this)) .withHoverEvent(new HoverEvent.ShowText(Component.translatable("skyblocker.helpers.hoppitysHunt.shareEggPrompt").withStyle(ChatFormatting.GREEN))) - ), - false + ) ); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/TimeTowerReminder.java b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/TimeTowerReminder.java index 95af6bf8a5..d5be330248 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/TimeTowerReminder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/TimeTowerReminder.java @@ -63,7 +63,7 @@ public static boolean checkIfTimeTower(Message message, boolean overlay) { private static void sendMessage() { if (Minecraft.getInstance().player == null || !Utils.isOnSkyblock()) return; if (SkyblockerConfigManager.get().helpers.chocolateFactory.enableTimeTowerReminder) { - Minecraft.getInstance().player.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.config.helpers.chocolateFactory.sendTimeTowerReminderMessage").withStyle(ChatFormatting.RED)), false); + Minecraft.getInstance().player.sendSystemMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.config.helpers.chocolateFactory.sendTimeTowerReminderMessage").withStyle(ChatFormatting.RED))); } File tempFile = SkyblockerMod.CONFIG_DIR.resolve(TIME_TOWER_FILE).toFile(); try { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/crimson/dojo/DojoManager.java b/src/main/java/de/hysky/skyblocker/skyblock/crimson/dojo/DojoManager.java index 916710c59a..7e6e400f9e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/crimson/dojo/DojoManager.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/crimson/dojo/DojoManager.java @@ -5,7 +5,7 @@ import de.hysky.skyblocker.events.ParticleEvents; import de.hysky.skyblocker.events.WorldEvents; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import de.hysky.skyblocker.utils.scheduler.Scheduler; import it.unimi.dsi.fastutil.booleans.BooleanPredicate; @@ -43,14 +43,14 @@ public class DojoManager { protected enum DojoChallenges { - NONE("none", enabled -> false), - FORCE("Force", enabled -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableForceHelper), - STAMINA("Stamina", enabled -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableStaminaHelper), - MASTERY("Mastery", enabled -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableMasteryHelper), - DISCIPLINE("Discipline", enabled -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableDisciplineHelper), - SWIFTNESS("Swiftness", enabled -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableSwiftnessHelper), - CONTROL("Control", enabled -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableControlHelper), - TENACITY("Tenacity", enabled -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableTenacityHelper); + NONE("none", _ -> false), + FORCE("Force", _ -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableForceHelper), + STAMINA("Stamina", _ -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableStaminaHelper), + MASTERY("Mastery", _ -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableMasteryHelper), + DISCIPLINE("Discipline", _ -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableDisciplineHelper), + SWIFTNESS("Swiftness", _ -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableSwiftnessHelper), + CONTROL("Control", _ -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableControlHelper), + TENACITY("Tenacity", _ -> SkyblockerConfigManager.get().crimsonIsle.dojo.enableTenacityHelper); private final String name; private final BooleanPredicate enabled; @@ -72,8 +72,8 @@ public static DojoChallenges from(String name) { @Init public static void init() { ClientReceiveMessageEvents.ALLOW_GAME.register(DojoManager::onMessage); - WorldRenderExtractionCallback.EVENT.register(DojoManager::extractRendering); - ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> reset()); + LevelRenderExtractionCallback.EVENT.register(DojoManager::extractRendering); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); ClientEntityEvents.ENTITY_LOAD.register(DojoManager::onEntitySpawn); ClientEntityEvents.ENTITY_UNLOAD.register(DojoManager::onEntityDespawn); AttackEntityCallback.EVENT.register(DojoManager::onEntityAttacked); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/DangerWarning.java b/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/DangerWarning.java index dcd0919ada..77f71cc611 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/DangerWarning.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/DangerWarning.java @@ -26,7 +26,7 @@ public class DangerWarning { @Init public static void init() { Scheduler.INSTANCE.scheduleCyclic(DangerWarning::updateIndicator, 5); - ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> reset()); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); } private static void updateIndicator() { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/Kuudra.java b/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/Kuudra.java index 3d62c505d4..d833eec745 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/Kuudra.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/Kuudra.java @@ -38,19 +38,19 @@ public class Kuudra { @Init public static void init() { DATA.load(); - ScreenEvents.AFTER_INIT.register((_client, screen, _scaledWidth, _scaledHeight) -> { + ScreenEvents.AFTER_INIT.register((_, screen, _, _) -> { if (Utils.isOnSkyblock() && screen instanceof ContainerScreen genericContainerScreen) { String title = screen.getTitle().getString(); Matcher factionShopMatcher = FACTION_SHOP_PATTERN.matcher(title); switch (title) { - case String s when factionShopMatcher.matches() -> { - ScreenEvents.afterTick(screen).register(_screen -> { + case String _ when factionShopMatcher.matches() -> { + ScreenEvents.afterTick(screen).register(_ -> { checkKuudraKeyShop(genericContainerScreen, factionShopMatcher); }); } case String s when s.startsWith("Pets") -> { - ScreenEvents.afterTick(screen).register(_screen -> { + ScreenEvents.afterTick(screen).register(_ -> { checkForKuudraPet(genericContainerScreen); }); } @@ -58,7 +58,7 @@ public static void init() { } } }); - ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> reset()); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); ClientReceiveMessageEvents.ALLOW_GAME.register(Kuudra::onMessage); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/KuudraWaypoints.java b/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/KuudraWaypoints.java index 609a786f23..87c587d5d3 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/KuudraWaypoints.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/KuudraWaypoints.java @@ -22,7 +22,7 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.PosUtils; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import de.hysky.skyblocker.utils.scheduler.Scheduler; import de.hysky.skyblocker.utils.waypoint.Waypoint; @@ -58,7 +58,7 @@ public class KuudraWaypoints { @Init public static void init() { - WorldRenderExtractionCallback.EVENT.register(KuudraWaypoints::extractRendering); + LevelRenderExtractionCallback.EVENT.register(KuudraWaypoints::extractRendering); ClientLifecycleEvents.CLIENT_STARTED.register(KuudraWaypoints::load); Scheduler.INSTANCE.scheduleCyclic(KuudraWaypoints::tick, 20); } @@ -67,7 +67,7 @@ private static void load(Minecraft client) { CompletableFuture safeSpots = loadWaypoints(client, SkyblockerMod.id("crimson/kuudra/safe_spot_waypoints.json"), SAFE_SPOT_WAYPOINTS, SAFE_SPOT_COLOR); CompletableFuture pearls = loadWaypoints(client, SkyblockerMod.id("crimson/kuudra/pearl_waypoints.json"), PEARL_WAYPOINTS, PEARL_COLOR); - CompletableFuture.allOf(safeSpots, pearls).whenComplete((_result, _throwable) -> loaded = true); + CompletableFuture.allOf(safeSpots, pearls).whenComplete((_, _) -> loaded = true); } private static CompletableFuture loadWaypoints(Minecraft client, Identifier file, ObjectArrayList list, float[] colorComponents) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/BloodCampHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/BloodCampHelper.java index 333e39f0af..9f921b2af8 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/BloodCampHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/BloodCampHelper.java @@ -4,7 +4,7 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -94,10 +94,10 @@ public class BloodCampHelper { public static void init() { ClientEntityEvents.ENTITY_LOAD.register(BloodCampHelper::onEntityLoad); ClientEntityEvents.ENTITY_UNLOAD.register(BloodCampHelper::onEntityUnload); - WorldRenderExtractionCallback.EVENT.register(BloodCampHelper::extractRendering); - ClientTickEvents.END_CLIENT_TICK.register(client -> tick()); - ClientPlayConnectionEvents.JOIN.register((h, s, c) -> reset()); - ClientPlayConnectionEvents.DISCONNECT.register((h, c) -> reset()); + LevelRenderExtractionCallback.EVENT.register(BloodCampHelper::extractRendering); + ClientTickEvents.END_CLIENT_TICK.register(_ -> tick()); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); + ClientPlayConnectionEvents.DISCONNECT.register((_, _) -> reset()); } private static void onEntityLoad(Entity entity, ClientLevel world) { @@ -122,7 +122,7 @@ private static void tick() { long now = System.currentTimeMillis(); // Process any newly loaded zombies waiting to be checked PENDING_WATCHERS.object2IntEntrySet().removeIf(e -> !e.getKey().isAlive()); - PENDING_WATCHERS.replaceAll((z, ticks) -> ticks - 1); + PENDING_WATCHERS.replaceAll((_, ticks) -> ticks - 1); PENDING_WATCHERS.object2IntEntrySet().removeIf(e -> { if (e.getIntValue() <= 0) { Zombie zombie = e.getKey(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonClass.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonClass.java index 83747aabb8..9971bda59a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonClass.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonClass.java @@ -2,12 +2,13 @@ import de.hysky.skyblocker.skyblock.entity.MobGlow; import de.hysky.skyblocker.skyblock.tabhud.util.Ico; +import de.hysky.skyblocker.utils.FlexibleItemStack; + import java.util.Arrays; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; import net.minecraft.util.ARGB; -import net.minecraft.world.item.ItemStack; public enum DungeonClass { UNKNOWN("Unknown", MobGlow.NO_GLOW, Ico.BARRIER), @@ -23,9 +24,9 @@ public enum DungeonClass { private final String name; private final int color; private final int glowColor; - private final ItemStack icon; + private final FlexibleItemStack icon; - DungeonClass(String name, int color, ItemStack icon) { + DungeonClass(String name, int color, FlexibleItemStack icon) { this.name = name; this.color = ARGB.opaque(color); this.glowColor = color; @@ -50,7 +51,7 @@ public int glowColor() { return this.glowColor; } - public ItemStack icon() { + public FlexibleItemStack icon() { return icon; } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java index 24ec503dbd..59a217c877 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java @@ -9,15 +9,15 @@ import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonMapUtils; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonPlayerManager; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.HudHelper; +import de.hysky.skyblocker.utils.render.GuiHelper; import de.hysky.skyblocker.utils.scheduler.Scheduler; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.command.v2.ClientCommands; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.rendering.v1.hud.HudElementRegistry; import net.fabricmc.fabric.api.client.rendering.v1.hud.VanillaHudElements; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.core.component.DataComponents; import net.minecraft.resources.Identifier; import net.minecraft.util.CommonColors; @@ -48,36 +48,36 @@ public class DungeonMap { @Init public static void init() { - HudElementRegistry.attachElementAfter(VanillaHudElements.STATUS_EFFECTS, DUNGEON_MAP, (context, tickCounter) -> render(context)); - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") - .then(ClientCommandManager.literal("hud") - .then(ClientCommandManager.literal("dungeon") + HudElementRegistry.attachElementAfter(VanillaHudElements.MOB_EFFECTS, DUNGEON_MAP, (context, _) -> extract(context)); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> dispatcher.register(ClientCommands.literal("skyblocker") + .then(ClientCommands.literal("hud") + .then(ClientCommands.literal("dungeon") .executes(Scheduler.queueOpenScreenCommand(DungeonMapConfigScreen::new)) ) ) )); - ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> reset()); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); } private static boolean shouldProcess() { return Utils.isInDungeons() && DungeonScore.isDungeonStarted() && !DungeonManager.isInBoss(); } - private static void render(GuiGraphics context) { + private static void extract(GuiGraphicsExtractor graphics) { DungeonsConfig.DungeonMap dungeonMap = SkyblockerConfigManager.get().dungeons.dungeonMap; if (shouldProcess() && dungeonMap.enableMap) { - render(context, dungeonMap.mapX, dungeonMap.mapY, dungeonMap.mapScaling, dungeonMap.fancyMap); + extract(graphics, dungeonMap.mapX, dungeonMap.mapY, dungeonMap.mapScaling, dungeonMap.fancyMap); } } - public static void render(GuiGraphics context, int x, int y, float scale, boolean fancy) { - render(context, x, y, scale, fancy, Integer.MIN_VALUE, Integer.MIN_VALUE, null); + public static void extract(GuiGraphicsExtractor context, int x, int y, float scale, boolean fancy) { + extractRenderState(context, x, y, scale, fancy, Integer.MIN_VALUE, Integer.MIN_VALUE, null); } /** * @return the {@link UUID} of the hovered player head, or null if no player head is hovered. */ - public static @Nullable UUID render(GuiGraphics context, int x, int y, float scale, boolean fancy, int mouseX, int mouseY, @Nullable UUID enlarge) { + public static @Nullable UUID extractRenderState(GuiGraphicsExtractor graphics, int x, int y, float scale, boolean fancy, int mouseX, int mouseY, @Nullable UUID enlarge) { Minecraft client = Minecraft.getInstance(); DungeonsConfig.DungeonMap dungeonMap = SkyblockerConfigManager.get().dungeons.dungeonMap; if (client.player == null || client.level == null) return null; @@ -86,19 +86,19 @@ public static void render(GuiGraphics context, int x, int y, float scale, boolea MapItemSavedData state = MapItem.getSavedData(mapId, client.level); if (state == null) return null; - context.pose().pushMatrix(); - context.pose().translate(x, y); - context.pose().scale(scale, scale); + graphics.pose().pushMatrix(); + graphics.pose().translate(x, y); + graphics.pose().scale(scale, scale); - if (dungeonMap.backgroundBlur) HudHelper.submitBlurredRectangle(context, 0, 0, 128, 128, 5); - if (dungeonMap.showOutline) HudHelper.drawBorder(context, 0, 0, 128, 128, CommonColors.LIGHT_GRAY); + if (dungeonMap.backgroundBlur) GuiHelper.blurredRectangle(graphics, 0, 0, 128, 128, 5); + if (dungeonMap.showOutline) GuiHelper.border(graphics, 0, 0, 128, 128, CommonColors.LIGHT_GRAY); - DungeonMapTexture.blitMap(context); - DungeonMapLabels.renderRoomNames(context); + DungeonMapTexture.blitMap(graphics); + DungeonMapLabels.extractRoomNames(graphics); UUID hoveredHead = null; - if (fancy) hoveredHead = renderPlayerHeads(context, client.level, state, mouseX / scale, mouseY / scale, enlarge); - context.pose().popMatrix(); + if (fancy) hoveredHead = extractPlayerHeads(graphics, client.level, state, mouseX / scale, mouseY / scale, enlarge); + graphics.pose().popMatrix(); return hoveredHead; } @@ -110,7 +110,7 @@ public static MapId getMapIdComponent(@Nullable ItemStack stack) { } else return cachedMapIdComponent != null ? cachedMapIdComponent : DEFAULT_MAP_ID_COMPONENT; } - private static @Nullable UUID renderPlayerHeads(GuiGraphics context, Level world, MapItemSavedData state, double mouseX, double mouseY, @Nullable UUID enlarge) { + private static @Nullable UUID extractPlayerHeads(GuiGraphicsExtractor graphics, Level level, MapItemSavedData state, double mouseX, double mouseY, @Nullable UUID enlarge) { if (!DungeonManager.isClearingDungeon()) return null; // Used to index through the player list to find which dungeon player corresponds to which map decoration. @@ -140,25 +140,25 @@ public static MapId getMapIdComponent(@Nullable ItemStack stack) { dungeonPlayerError(mapDecoration.getKey(), "has null uuid", i - 1, DungeonPlayerManager.getPlayers(), ((MapItemSavedDataAccessor) state).getDecorations()); continue; } - PlayerRenderState player = PlayerRenderState.of(world, dungeonPlayer, mapDecoration.getValue()); + PlayerRenderState player = PlayerRenderState.of(level, dungeonPlayer, mapDecoration.getValue()); // Actually render the player head - context.pose().pushMatrix(); - context.pose().translate((float) player.mapPos().x(), (float) player.mapPos().y()); - context.pose().rotate((float) Math.toRadians(player.deg() + 180f)); + graphics.pose().pushMatrix(); + graphics.pose().translate((float) player.mapPos().x(), (float) player.mapPos().y()); + graphics.pose().rotate((float) Math.toRadians(player.deg() + 180f)); if (player.uuid().equals(enlarge)) { // Enlarge the player head when the corresponding button is hovered - context.pose().scale(2, 2); + graphics.pose().scale(2, 2); } else if (hovered == null && isPlayerHovered(player, mouseX, mouseY)) { // Enlarge the player head when hovered - context.pose().scale(2, 2); + graphics.pose().scale(2, 2); hovered = player.uuid(); } - HudHelper.drawPlayerHead(context, -4, -4, 8, player.uuid()); - HudHelper.drawBorder(context, -5, -5, 10, 10, dungeonPlayer.dungeonClass().color()); - context.fill(-1, -7, 1, -5, dungeonPlayer.dungeonClass().color()); - context.pose().popMatrix(); + GuiHelper.playerHead(graphics, -4, -4, 8, player.uuid()); + GuiHelper.border(graphics, -5, -5, 10, 10, dungeonPlayer.dungeonClass().color()); + graphics.fill(-1, -7, 1, -5, dungeonPlayer.dungeonClass().color()); + graphics.pose().popMatrix(); } return hovered; } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java index 7fa4be05b2..39df17379c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapConfigScreen.java @@ -1,7 +1,7 @@ package de.hysky.skyblocker.skyblock.dungeon; import java.awt.Color; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.client.renderer.RenderPipelines; @@ -13,7 +13,7 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.utils.render.HudHelper; +import de.hysky.skyblocker.utils.render.GuiHelper; public class DungeonMapConfigScreen extends Screen { @@ -34,11 +34,11 @@ public DungeonMapConfigScreen(@Nullable Screen parent) { } @Override - public void render(GuiGraphics context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); - renderHUDMap(context, mapX, mapY); - renderHUDScore(context, scoreX, scoreY); - context.drawCenteredString(font, "Right Click To Reset Position", width >> 1, height >> 1, Color.GRAY.getRGB()); + public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractRenderState(graphics, mouseX, mouseY, a); + extractHUDMap(graphics, mapX, mapY); + extractHUDScore(graphics, scoreX, scoreY); + graphics.centeredText(font, "Right Click To Reset Position", width >> 1, height >> 1, Color.GRAY.getRGB()); } @Override @@ -47,10 +47,10 @@ public boolean mouseDragged(MouseButtonEvent click, double offsetX, double offse float scoreScaling = SkyblockerConfigManager.get().dungeons.dungeonScore.scoreScaling; int scoreWidth = (int) (font.width(DungeonScoreHUD.getFormattedScoreText()) * scoreScaling); int scoreHeight = (int) (font.lineHeight * scoreScaling); - if (HudHelper.pointIsInArea(click.x(), click.y(), mapX, mapY, mapX + mapSize, mapY + mapSize) && click.button() == 0) { + if (GuiHelper.pointIsInArea(click.x(), click.y(), mapX, mapY, mapX + mapSize, mapY + mapSize) && click.button() == 0) { mapX = (int) Math.max(Math.min(click.x() - (mapSize >> 1), this.width - mapSize), 0); mapY = (int) Math.max(Math.min(click.y() - (mapSize >> 1), this.height - mapSize), 0); - } else if (HudHelper.pointIsInArea(click.x(), click.y(), scoreX, scoreY, scoreX + scoreWidth, scoreY + scoreHeight) && click.button() == 0) { + } else if (GuiHelper.pointIsInArea(click.x(), click.y(), scoreX, scoreY, scoreX + scoreWidth, scoreY + scoreHeight) && click.button() == 0) { scoreX = (int) Math.max(Math.min(click.x() - (scoreWidth >> 1), this.width - scoreWidth), 0); scoreY = (int) Math.max(Math.min(click.y() - (scoreHeight >> 1), this.height - scoreHeight), 0); } @@ -81,15 +81,15 @@ public void onClose() { this.minecraft.setScreen(parent); } - public void renderHUDMap(GuiGraphics context, int x, int y) { + public void extractHUDMap(GuiGraphicsExtractor graphics, int x, int y) { float scaling = SkyblockerConfigManager.get().dungeons.dungeonMap.mapScaling; int size = (int) (128 * scaling); - context.blit(RenderPipelines.GUI_TEXTURED, EXAMPLE_MAP, x, y, 0, 0, size, size, size, size); + graphics.blit(RenderPipelines.GUI_TEXTURED, EXAMPLE_MAP, x, y, 0, 0, size, size, size, size); - if (SkyblockerConfigManager.get().dungeons.dungeonMap.showOutline) HudHelper.drawBorder(context, x, y, size, size, CommonColors.LIGHT_GRAY); + if (SkyblockerConfigManager.get().dungeons.dungeonMap.showOutline) GuiHelper.border(graphics, x, y, size, size, CommonColors.LIGHT_GRAY); } - public void renderHUDScore(GuiGraphics context, int x, int y) { - DungeonScoreHUD.render(context, x, y); + public void extractHUDScore(GuiGraphicsExtractor graphics, int x, int y) { + DungeonScoreHUD.extractRenderState(graphics, x, y); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapLabels.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapLabels.java index bd645c3a9c..2bee9f519b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapLabels.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapLabels.java @@ -8,7 +8,7 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.util.CommonColors; @@ -27,7 +27,7 @@ import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonMapUtils; import de.hysky.skyblocker.skyblock.dungeon.secrets.Room; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.HudHelper; +import de.hysky.skyblocker.utils.render.GuiHelper; import de.hysky.skyblocker.utils.scheduler.Scheduler; public class DungeonMapLabels { @@ -37,7 +37,7 @@ public class DungeonMapLabels { @Init public static void init() { - ClientPlayConnectionEvents.JOIN.register((_n, _p, _c) -> DungeonMapLabels.clearLabels()); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> DungeonMapLabels.clearLabels()); DungeonEvents.DUNGEON_ENDED.register(DungeonMapLabels::clearLabels); DungeonEvents.ROOM_MATCHED.register(DungeonMapLabels::onRoomMatched); Scheduler.INSTANCE.scheduleCyclic(() -> updateRoomNames(null), 20); @@ -112,16 +112,16 @@ private static Component getLabelForRoom(Room room, String roomName) { }; } - protected static void renderRoomNames(GuiGraphics context) { + protected static void extractRoomNames(GuiGraphicsExtractor graphics) { if (!SkyblockerConfigManager.get().dungeons.dungeonMap.showRoomLabels) return; Font textRenderer = Minecraft.getInstance().font; for (RoomLabel label : LABELS.values()) { - context.pose().pushMatrix(); - context.pose().translate(label.x, label.y); - context.pose().scale(LABEL_SCALE); - drawText(context, textRenderer, label.textLines, label.color); - context.pose().popMatrix(); + graphics.pose().pushMatrix(); + graphics.pose().translate(label.x, label.y); + graphics.pose().scale(LABEL_SCALE); + extractText(graphics, textRenderer, label.textLines, label.color); + graphics.pose().popMatrix(); } } @@ -200,11 +200,11 @@ private static int getMaxWidth(Room room, int mapRoomSize) { return (int) (maxWidth * MAX_WIDTH_SCALAR); } - private static void drawText(GuiGraphics context, Font textRenderer, List lines, int color) { + private static void extractText(GuiGraphicsExtractor graphics, Font textRenderer, List lines, int color) { int y = lines.size() > 1 ? -(textRenderer.lineHeight / 2) * (lines.size() - 1) : 0; for (FormattedCharSequence orderedText : lines) { int textWidth = textRenderer.width(orderedText) / 2; - HudHelper.drawOutlinedText(context, orderedText, -textWidth, y, color, CommonColors.BLACK); + GuiHelper.outlinedText(graphics, orderedText, -textWidth, y, color, CommonColors.BLACK); y += 9; } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapTexture.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapTexture.java index 6eb720d609..7b153ac803 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapTexture.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMapTexture.java @@ -23,10 +23,10 @@ import de.hysky.skyblocker.utils.Utils; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldTerrainRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelTerrainRenderContext; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.renderer.MapRenderer; import net.minecraft.client.renderer.state.MapRenderState; import net.minecraft.client.renderer.texture.DynamicTexture; @@ -57,9 +57,9 @@ public static void init() { dungeonMapTexture = new DynamicTexture(() -> "Skyblocker Dungeon Map", MAP_TEXTURE_SIZE, MAP_TEXTURE_SIZE, true); minecraft.getTextureManager().register(ID, dungeonMapTexture); }); - ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> clearMapImage()); - DungeonEvents.ROOM_MATCHED.register((_room) -> onMapItemDataUpdate(DungeonMap.getMapIdComponent(null), true)); - WorldRenderEvents.START_MAIN.register(DungeonMapTexture::uploadMapTexture); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> clearMapImage()); + DungeonEvents.ROOM_MATCHED.register(_ -> onMapItemDataUpdate(DungeonMap.getMapIdComponent(null), true)); + LevelRenderEvents.START_MAIN.register(DungeonMapTexture::uploadMapTexture); } public static void onMapItemDataUpdate(MapId mapId, boolean updateMapTexture) { @@ -185,15 +185,15 @@ private static void clearMapImage() { * Upload the map texture to the GPU at the start of the game, this is to ensure this runs on the GPU * for the thread split. */ - private static void uploadMapTexture(WorldTerrainRenderContext context) { + private static void uploadMapTexture(LevelTerrainRenderContext context) { if (dungeonMapTexture != null && requiresUpload) { dungeonMapTexture.upload(); requiresUpload = false; } } - protected static void blitMap(GuiGraphics graphics) { - graphics.submitMapRenderState(MAP_RENDER_STATE); + protected static void blitMap(GuiGraphicsExtractor graphics) { + graphics.map(MAP_RENDER_STATE); } public static void close() { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java index 809c5f1c05..942c5bd68a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java @@ -83,7 +83,7 @@ public class DungeonScore { @Init public static void init() { Scheduler.INSTANCE.scheduleCyclic(DungeonScore::tick, 20); - ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> reset()); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); DungeonEvents.DUNGEON_STARTED.register(DungeonScore::onDungeonStart); DungeonEvents.DUNGEON_ENDED.register(DungeonScore::reset); ClientReceiveMessageEvents.ALLOW_GAME.register((message, overlay) -> { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScoreHUD.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScoreHUD.java index 75a6ff0b6a..8f081364d6 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScoreHUD.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScoreHUD.java @@ -10,7 +10,7 @@ import net.fabricmc.fabric.api.client.rendering.v1.hud.VanillaHudElements; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; @@ -22,26 +22,26 @@ private DungeonScoreHUD() { @Init public static void init() { - HudElementRegistry.attachElementAfter(VanillaHudElements.OVERLAY_MESSAGE, DUNGEON_SCORE, (context, tickCounter) -> render(context)); + HudElementRegistry.attachElementAfter(VanillaHudElements.OVERLAY_MESSAGE, DUNGEON_SCORE, (graphics, _) -> extractRenderState(graphics)); } //This is 4+5 wide, needed to offset the extra width from bold numbers (3×1 wide) in S+ and the "+" (6 wide) so that it doesn't go off the screen if the score is S+ and the hud element is at the right edge of the screen private static final Component extraSpace = Component.literal(" ").append(Component.literal(" ").withStyle(ChatFormatting.BOLD)); - private static void render(GuiGraphics context) { + private static void extractRenderState(GuiGraphicsExtractor graphics) { if (Utils.isInDungeons() && DungeonScore.isDungeonStarted() && SkyblockerConfigManager.get().dungeons.dungeonScore.enableScoreHUD) { int x = SkyblockerConfigManager.get().dungeons.dungeonScore.scoreX; int y = SkyblockerConfigManager.get().dungeons.dungeonScore.scoreY; - render(context, x, y); + extractRenderState(graphics, x, y); } } - public static void render(GuiGraphics context, int x, int y) { + public static void extractRenderState(GuiGraphicsExtractor graphics, int x, int y) { float scale = SkyblockerConfigManager.get().dungeons.dungeonScore.scoreScaling; - Matrix3x2fStack matrixStack = context.pose(); + Matrix3x2fStack matrixStack = graphics.pose(); matrixStack.pushMatrix(); matrixStack.scale(scale, scale); - context.drawString(Minecraft.getInstance().font, getFormattedScoreText(), (int) (x / scale), (int) (y / scale), 0xFFFFFFFF); + graphics.text(Minecraft.getInstance().font, getFormattedScoreText(), (int) (x / scale), (int) (y / scale), 0xFFFFFFFF); matrixStack.popMatrix(); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/FireFreezeStaffTimer.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/FireFreezeStaffTimer.java index c8ce6076a7..7664839ad6 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/FireFreezeStaffTimer.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/FireFreezeStaffTimer.java @@ -12,7 +12,7 @@ import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; import net.minecraft.util.CommonColors; @@ -24,9 +24,9 @@ public class FireFreezeStaffTimer { @Init public static void init() { - HudElementRegistry.attachElementAfter(VanillaHudElements.OVERLAY_MESSAGE, FIRE_FREEZE_STAFF_TIMER, FireFreezeStaffTimer::onDraw); + HudElementRegistry.attachElementAfter(VanillaHudElements.OVERLAY_MESSAGE, FIRE_FREEZE_STAFF_TIMER, FireFreezeStaffTimer::extractRenderState); ClientReceiveMessageEvents.ALLOW_GAME.register(FireFreezeStaffTimer::onChatMessage); - ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> FireFreezeStaffTimer.reset()); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> FireFreezeStaffTimer.reset()); ServerTickCallback.EVENT.register(FireFreezeStaffTimer::onServerTick); } @@ -34,7 +34,7 @@ private static void onServerTick() { if (timerActive) fireFreezeTimer -= 50; } - private static void onDraw(GuiGraphics context, DeltaTracker tickCounter) { + private static void extractRenderState(GuiGraphicsExtractor graphics, DeltaTracker tickCounter) { Minecraft client = Minecraft.getInstance(); if (client.screen != null) return; @@ -56,7 +56,7 @@ private static void onDraw(GuiGraphics context, DeltaTracker tickCounter) { int width = client.getWindow().getGuiScaledWidth() / 2; int height = client.getWindow().getGuiScaledHeight() / 2; - context.drawCenteredString(renderer, Component.literal("Fire Freeze ").append(message), width, height, CommonColors.WHITE); + graphics.centeredText(renderer, Component.literal("Fire Freeze ").append(message), width, height, CommonColors.WHITE); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/GoldorWaypointsManager.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/GoldorWaypointsManager.java index 0855fae1c8..4972fa75d5 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/GoldorWaypointsManager.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/GoldorWaypointsManager.java @@ -10,7 +10,7 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import de.hysky.skyblocker.utils.waypoint.NamedWaypoint; import de.hysky.skyblocker.utils.waypoint.Waypoint; @@ -70,16 +70,16 @@ public class GoldorWaypointsManager { @Init public static void init() { - WorldRenderExtractionCallback.EVENT.register(GoldorWaypointsManager::extractRendering); + LevelRenderExtractionCallback.EVENT.register(GoldorWaypointsManager::extractRendering); ClientLifecycleEvents.CLIENT_STARTED.register(GoldorWaypointsManager::load); ClientReceiveMessageEvents.ALLOW_GAME.register(GoldorWaypointsManager::onChatMessage); - ClientPlayConnectionEvents.JOIN.register(((handler, sender, client) -> reset())); + ClientPlayConnectionEvents.JOIN.register(((_, _, _) -> reset())); } private static void load(Minecraft client) { CompletableFuture terminals = loadWaypoints(client, SkyblockerMod.id("dungeons/goldorwaypoints.json")); - terminals.whenComplete((_result, _throwable) -> loaded = true); + terminals.whenComplete((_, _) -> loaded = true); } private static CompletableFuture loadWaypoints(Minecraft client, Identifier file) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/GuardianHealth.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/GuardianHealth.java index c633664a71..1a4f206039 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/GuardianHealth.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/GuardianHealth.java @@ -4,7 +4,7 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.RenderHelper; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; @@ -28,8 +28,8 @@ public class GuardianHealth { @Init public static void init() { ClientReceiveMessageEvents.ALLOW_GAME.register(GuardianHealth::onChatMessage); - ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> GuardianHealth.reset()); - WorldRenderExtractionCallback.EVENT.register(GuardianHealth::extractRendering); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> GuardianHealth.reset()); + LevelRenderExtractionCallback.EVENT.register(GuardianHealth::extractRendering); } private static void extractRendering(PrimitiveCollector collector) { @@ -40,7 +40,7 @@ private static void extractRendering(PrimitiveCollector collector) { if (Utils.isInDungeons() && inBoss && client.player != null && client.level != null) { List guardians = client.level.getEntitiesOfClass( - Guardian.class, bossRoom, guardianEntity -> true); + Guardian.class, bossRoom, _ -> true); for (Guardian guardian : guardians) { List armorStands = diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LeapOverlay.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LeapOverlay.java index 44aba62219..2c39d24c3d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LeapOverlay.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LeapOverlay.java @@ -7,7 +7,7 @@ import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonPlayerManager; import de.hysky.skyblocker.utils.Constants; import de.hysky.skyblocker.utils.ItemUtils; -import de.hysky.skyblocker.utils.render.HudHelper; +import de.hysky.skyblocker.utils.render.GuiHelper; import de.hysky.skyblocker.utils.scheduler.MessageScheduler; import org.joml.Matrix3x2fStack; import org.jspecify.annotations.Nullable; @@ -20,7 +20,7 @@ import java.util.UUID; import java.util.function.Supplier; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.layouts.FrameLayout; @@ -39,7 +39,7 @@ import net.minecraft.util.CommonColors; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.ContainerListener; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -177,9 +177,9 @@ public MapWidget(int x, int y) { } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delta) { - LeapOverlay.this.hovered = DungeonMap.render(context, getX(), getY(), CONFIG.get().scale, true, mouseX - getX(), mouseY - getY(), getChildAt(mouseX, mouseY).filter(PlayerButton.class::isInstance).map(PlayerButton.class::cast).map(p -> p.reference.uuid()).orElse(null)); - HudHelper.drawBorder(context, getX(), getY(), (int) (128 * CONFIG.get().scale), (int) (128 * CONFIG.get().scale), CommonColors.WHITE); + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + LeapOverlay.this.hovered = DungeonMap.extractRenderState(graphics, getX(), getY(), CONFIG.get().scale, true, mouseX - getX(), mouseY - getY(), getChildAt(mouseX, mouseY).filter(PlayerButton.class::isInstance).map(PlayerButton.class::cast).map(p -> p.reference.uuid()).orElse(null)); + GuiHelper.border(graphics, getX(), getY(), (int) (128 * CONFIG.get().scale), (int) (128 * CONFIG.get().scale), CommonColors.WHITE); } @Override @@ -203,16 +203,16 @@ private class PlayerButton extends Button { private final PlayerReference reference; private PlayerButton(int x, int y, int width, int height, PlayerReference reference) { - super(x, y, width, height, Component.empty(), b -> {}, ts -> Component.empty()); + super(x, y, width, height, Component.empty(), _ -> {}, _ -> Component.empty()); this.reference = reference; } @Override - protected void renderContents(GuiGraphics context, int mouseX, int mouseY, float delta) { + protected void extractContents(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { Identifier texture = this.isHoveredOrFocused() || reference.uuid().equals(LeapOverlay.this.hovered) ? BUTTON_HIGHLIGHTED : BUTTON; - context.blitSprite(RenderPipelines.GUI_TEXTURED, texture, this.getX(), this.getY(), this.getWidth(), this.getHeight()); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, texture, this.getX(), this.getY(), this.getWidth(), this.getHeight()); - Matrix3x2fStack matrices = context.pose(); + Matrix3x2fStack matrices = graphics.pose(); float scale = CONFIG.get().scale; int baseX = this.getX() + BORDER_THICKNESS; int centreX = this.getX() + (this.getWidth() >> 1); @@ -220,20 +220,20 @@ protected void renderContents(GuiGraphics context, int mouseX, int mouseY, float int halfFontHeight = (int) (CLIENT.font.lineHeight * scale) >> 1; //Draw Player Head - HudHelper.drawPlayerHead(context, baseX + 4, centreY - ((int) (HEAD_SIZE * scale) >> 1), (int) (HEAD_SIZE * scale), reference.uuid()); + GuiHelper.playerHead(graphics, baseX + 4, centreY - ((int) (HEAD_SIZE * scale) >> 1), (int) (HEAD_SIZE * scale), reference.uuid()); //Draw class as heading matrices.pushMatrix(); matrices.translate(centreX, this.getY() + halfFontHeight); matrices.scale(scale, scale); - context.drawCenteredString(CLIENT.font, reference.dungeonClass().displayName(), 0, 0, reference.dungeonClass().color()); + graphics.centeredText(CLIENT.font, reference.dungeonClass().displayName(), 0, 0, reference.dungeonClass().color()); matrices.popMatrix(); //Draw name next to head matrices.pushMatrix(); matrices.translate(baseX + HEAD_SIZE * scale + 8, centreY - halfFontHeight); matrices.scale(scale, scale); - context.drawString(CLIENT.font, Component.literal(reference.name()), 0, 0, CommonColors.WHITE); + graphics.text(CLIENT.font, Component.literal(reference.name()), 0, 0, CommonColors.WHITE); matrices.popMatrix(); if (reference.status() != null) { @@ -241,11 +241,11 @@ protected void renderContents(GuiGraphics context, int mouseX, int mouseY, float matrices.pushMatrix(); matrices.translate(centreX, this.getY() + this.getHeight() - (halfFontHeight * 3)); matrices.scale(scale, scale); - context.drawCenteredString(CLIENT.font, reference.status().text.get(), 0, 0, CommonColors.WHITE); + graphics.centeredText(CLIENT.font, reference.status().text.get(), 0, 0, CommonColors.WHITE); matrices.popMatrix(); //Overlay - context.fill(this.getX(), this.getY(), this.getX() + this.getWidth(), this.getY() + this.getHeight(), reference.status().overlayColor); + graphics.fill(this.getX(), this.getY(), this.getX() + this.getWidth(), this.getY() + this.getHeight(), reference.status().overlayColor); } } @@ -277,7 +277,7 @@ public int compareTo(LeapOverlay.PlayerReference o) { } private void clickSlot() { - CLIENT.gameMode.handleInventoryMouseClick(this.syncId(), this.slotId(), GLFW.GLFW_MOUSE_BUTTON_LEFT, ClickType.PICKUP, CLIENT.player); + CLIENT.gameMode.handleContainerInput(this.syncId(), this.slotId(), GLFW.GLFW_MOUSE_BUTTON_LEFT, ContainerInput.PICKUP, CLIENT.player); if (CONFIG.get().enableLeapMessage) { MessageScheduler.INSTANCE.sendMessageAfterCooldown("/pc " + Constants.PREFIX.get().getString() + CONFIG.get().leapMessage.replaceAll("\\[name]", this.name), true); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LividColor.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LividColor.java index 39ab1546d9..eecfe21977 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LividColor.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/LividColor.java @@ -6,7 +6,7 @@ import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.utils.Constants; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import de.hysky.skyblocker.utils.scheduler.MessageScheduler; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; @@ -60,8 +60,8 @@ public class LividColor { @Init public static void init() { - ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> LividColor.reset()); - WorldRenderExtractionCallback.EVENT.register(LividColor::update); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> LividColor.reset()); + LevelRenderExtractionCallback.EVENT.register(LividColor::update); } private static void update(PrimitiveCollector collector) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/RareRoomAlert.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/RareRoomAlert.java index 596f3fa2b7..f8dcca3a45 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/RareRoomAlert.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/RareRoomAlert.java @@ -54,6 +54,6 @@ private static void showAlert(String roomId) { TitleContainer.addTitle(new Title(Component.literal(roomName.toUpperCase(Locale.ENGLISH)).withStyle(ChatFormatting.LIGHT_PURPLE)), 100); TitleContainer.playNotificationSound(); - CLIENT.player.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.dungeons.rareRoomAlert.foundRoom", roomName)), false); + CLIENT.player.sendSystemMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.dungeons.rareRoomAlert.foundRoom", roomName))); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/Reparty.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/Reparty.java index 0dc793b54a..f51779dd29 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/Reparty.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/Reparty.java @@ -13,8 +13,8 @@ import net.azureaaron.hmapi.network.packet.s2c.ErrorS2CPacket; import net.azureaaron.hmapi.network.packet.s2c.HypixelS2CPacket; import net.azureaaron.hmapi.network.packet.v2.s2c.PartyInfoS2CPacket; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.command.v2.ClientCommands; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; @@ -43,9 +43,9 @@ public Reparty() { "\nYou have 60 seconds to accept. Click here to join!\n.*)$"); HypixelPacketEvents.PARTY_INFO.register(this::onPacket); - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { - dispatcher.register(ClientCommandManager.literal("reparty").executes(this::executeCommand)); - dispatcher.register(ClientCommandManager.literal("rp").executes(this::executeCommand)); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> { + dispatcher.register(ClientCommands.literal("reparty").executes(this::executeCommand)); + dispatcher.register(ClientCommands.literal("rp").executes(this::executeCommand)); }); } @@ -78,14 +78,14 @@ case PartyInfoS2CPacket(var inParty, var members) when this.repartying -> { Scheduler.INSTANCE.schedule(() -> this.repartying = false, count * BASE_DELAY); } else { assert CLIENT.player != null; - CLIENT.player.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.reparty.notInPartyOrNotLeader")), false); + CLIENT.player.sendSystemMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.reparty.notInPartyOrNotLeader"))); this.repartying = false; } } case ErrorS2CPacket(var id, var error) when id.equals(PartyInfoS2CPacket.ID) && this.repartying -> { assert CLIENT.player != null; - CLIENT.player.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.reparty.error")), false); + CLIENT.player.sendSystemMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.reparty.error"))); LOGGER.error("[Skyblocker Reparty] The party info packet returned an unexpected error! {}", error); this.repartying = false; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/ArrowAlign.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/ArrowAlign.java index 3bfeac5273..e3bc59d556 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/ArrowAlign.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/ArrowAlign.java @@ -8,7 +8,7 @@ import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.utils.ColorUtils; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; @@ -24,7 +24,7 @@ import java.util.List; import java.util.Optional; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; public class ArrowAlign { private static final BlockPos LEFT_TOP = new BlockPos(-2, 124, 79); @@ -36,10 +36,10 @@ public class ArrowAlign { @Init public static void init() { - ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> reset()); - WorldRenderExtractionCallback.EVENT.register(ArrowAlign::extractRendering); - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("device").then(literal("arrow-align") - .then(literal("solve").executes(context -> { + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); + LevelRenderExtractionCallback.EVENT.register(ArrowAlign::extractRendering); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("dungeons").then(literal("device").then(literal("arrow-align") + .then(literal("solve").executes(_ -> { findSolution(); return Command.SINGLE_SUCCESS; })) @@ -68,7 +68,7 @@ private static void extractRendering(PrimitiveCollector collector) { } private static List getFrameEntitiesList() { - return Minecraft.getInstance().level.getEntitiesOfClass(ItemFrame.class, FRAMES_AREA, frame -> true); + return Minecraft.getInstance().level.getEntitiesOfClass(ItemFrame.class, FRAMES_AREA, _ -> true); } private static int getSolutionIndex(BlockPos pos) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java index 016361cae9..906e0fee1d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java @@ -7,7 +7,7 @@ import de.hysky.skyblocker.utils.ColorUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.RenderHelper; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; @@ -35,7 +35,7 @@ public class LightsOn { @Init public static void init() { - WorldRenderExtractionCallback.EVENT.register(LightsOn::extractRendering); + LevelRenderExtractionCallback.EVENT.register(LightsOn::extractRendering); } private static void extractRendering(PrimitiveCollector collector) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java index 95f629d87d..486ebd180b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java @@ -8,7 +8,7 @@ import de.hysky.skyblocker.utils.ColorUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.RenderHelper; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectList; @@ -46,8 +46,8 @@ public class SimonSays { @Init public static void init() { UseBlockCallback.EVENT.register(SimonSays::onBlockInteract); - ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> reset()); - WorldRenderExtractionCallback.EVENT.register(SimonSays::extractRendering); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); + LevelRenderExtractionCallback.EVENT.register(SimonSays::extractRendering); WorldEvents.BLOCK_STATE_UPDATE.register(SimonSays::onBlockUpdate); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/TargetPractice.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/TargetPractice.java index 4502d2aaf8..deaceb346f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/TargetPractice.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/TargetPractice.java @@ -10,7 +10,7 @@ import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.utils.ColorUtils; import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.render.WorldRenderExtractionCallback; +import de.hysky.skyblocker.utils.render.LevelRenderExtractionCallback; import de.hysky.skyblocker.utils.render.primitive.PrimitiveCollector; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.minecraft.core.BlockPos; @@ -35,8 +35,8 @@ public class TargetPractice { @Init public static void init() { WorldEvents.BLOCK_STATE_UPDATE.register(TargetPractice::onBlockStateUpdate); - WorldRenderExtractionCallback.EVENT.register(TargetPractice::extractRendering); - ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> reset()); + LevelRenderExtractionCallback.EVENT.register(TargetPractice::extractRendering); + ClientPlayConnectionEvents.JOIN.register((_, _, _) -> reset()); } private static void onBlockStateUpdate(BlockPos pos, BlockState oldState, BlockState newState) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/FinderSettingsContainer.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/FinderSettingsContainer.java index 4baded150f..0429a62bca 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/FinderSettingsContainer.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/FinderSettingsContainer.java @@ -3,8 +3,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.AbstractContainerWidget; +import net.minecraft.client.gui.components.AbstractScrollArea; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.input.MouseButtonEvent; @@ -30,7 +31,7 @@ public class FinderSettingsContainer extends AbstractContainerWidget { public FinderSettingsContainer(int x, int y, int height) { - super(x, y, 336, height, Component.empty()); + super(x, y, 336, height, Component.empty(), AbstractScrollArea.defaultSettings(4)); } @Override @@ -169,8 +170,8 @@ private boolean setRangeFromTooltip(ItemStack stack, RangedValueWidget widget) { //System.out.println("Min and max: " + minAndMax[0] + " " + minAndMax[1]); int leMin = -1; int leMax = -1; - try { leMin = Integer.parseInt(minAndMax[0].trim()); } catch (NumberFormatException ignored) {} - try { leMax = Integer.parseInt(minAndMax[1].trim()); } catch (NumberFormatException ignored) {} + try { leMin = Integer.parseInt(minAndMax[0].trim()); } catch (NumberFormatException _) {} + try { leMax = Integer.parseInt(minAndMax[1].trim()); } catch (NumberFormatException _) {} widget.setMinAndMax(leMin, leMax); return true; @@ -275,15 +276,15 @@ public boolean mouseClicked(MouseButtonEvent click, boolean doubled) { } @Override - protected void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delta) { + protected void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { if (!visible || !isInitialized) return; - this.classLevelRange.render(context, mouseX, mouseY, delta); - this.dungeonLevelRange.render(context, mouseX, mouseY, delta); + this.classLevelRange.extractRenderState(graphics, mouseX, mouseY, a); + this.dungeonLevelRange.extractRenderState(graphics, mouseX, mouseY, a); // Render the dropdowns last to fix overlap issue. - this.sortGroupsSelector.render(context, mouseX, mouseY, delta); - this.floorSelector.render(context, mouseX, mouseY, delta); - this.dungeonTypeSelector.render(context, mouseX, mouseY, delta); + this.sortGroupsSelector.extractRenderState(graphics, mouseX, mouseY, a); + this.floorSelector.extractRenderState(graphics, mouseX, mouseY, a); + this.dungeonTypeSelector.extractRenderState(graphics, mouseX, mouseY, a); } @Override diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java index f0eb56057b..35680995d4 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java @@ -5,8 +5,7 @@ import java.util.List; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.GuiGraphics.HoveredTextEffects; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.AbstractSelectionList; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.input.MouseButtonEvent; @@ -77,35 +76,35 @@ public boolean mouseClicked(MouseButtonEvent click, boolean doubled) { protected void updateWidgetNarration(NarrationElementOutput builder) {} @Override - public void renderWidget(GuiGraphics context, int mouseX, int mouseY, float delta) { + public void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { if (isOpen) { - if (animationProgress < 1) animationProgress += delta * 0.5f; + if (animationProgress < 1) animationProgress += a * 0.5f; else if (animationProgress != 1) animationProgress = 1; } else { animationProgress = 0; } if (PartyFinderScreen.DEBUG) { - context.drawString(Minecraft.getInstance().font, String.valueOf(slotId), getX(), getY() - 10, CommonColors.RED, true); - context.drawString(Minecraft.getInstance().font, String.valueOf(backButtonId), getX() + 50, getY() - 10, CommonColors.RED, true); - context.drawString(minecraft.font, String.valueOf(animationProgress), getX() - 10, getY(), CommonColors.GREEN, true); + graphics.text(Minecraft.getInstance().font, String.valueOf(slotId), getX(), getY() - 10, CommonColors.RED, true); + graphics.text(Minecraft.getInstance().font, String.valueOf(backButtonId), getX() + 50, getY() - 10, CommonColors.RED, true); + graphics.text(minecraft.font, String.valueOf(animationProgress), getX() - 10, getY(), CommonColors.GREEN, true); } if (isOpen) { int listHeight = Math.min(getHeight(), contentHeight() - header.getHeight() - 4); int openedListHeight = isOpen ? (int) (listHeight * animationProgress) : (int) (listHeight * (1 - animationProgress)); - context.fill(getX(), header.getY() + header.getHeight(), getX() + getWidth() - 1, header.getY() + openedListHeight + header.getHeight(), 0xFFF0F0F0); - context.fill(getX() + 1, header.getY() + header.getHeight() + 1, getX() + getWidth() - 2, header.getY() + openedListHeight + header.getHeight() - 1, CommonColors.BLACK); + graphics.fill(getX(), header.getY() + header.getHeight(), getX() + getWidth() - 1, header.getY() + openedListHeight + header.getHeight(), 0xFFF0F0F0); + graphics.fill(getX() + 1, header.getY() + header.getHeight() + 1, getX() + getWidth() - 2, header.getY() + openedListHeight + header.getHeight() - 1, CommonColors.BLACK); } - super.renderWidget(context, mouseX, mouseY, delta); + super.extractWidgetRenderState(graphics, mouseX, mouseY, a); } @Override - protected void renderListSeparators(GuiGraphics context) { + protected void extractListSeparators(GuiGraphicsExtractor graphics) { } @Override - protected void renderListBackground(GuiGraphics context) { + protected void extractListBackground(GuiGraphicsExtractor graphics) { } public void open(List