diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7058301..02ecd97 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,9 @@ name: Build JAR on: push: branches: [ main, master ] + paths-ignore: + - '*.md' + - '.github/**' pull_request: branches: [ main, master ] release: diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..0439f79 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,36 @@ +# Pupper Client AI Agent Guide + +## Architecture Overview +- **Mod Structure**: Fabric mod with singleton `PupperClient` managing specialized managers (ModManager, EventBus, etc.) +- **Event System**: Custom `EventBus` using reflection for `@EventListener` methods and `EventListener` fields +- **Mods**: Categorized features (HUD, player, render, misc) in `management/mod/impl/` +- **Rendering**: Skia-based UI in `skia/` package, custom shaders in `shader/` +- **Integration**: ViaFabricPlus for version switching, WebSocket for real-time features + +## Key Workflows +- **Build**: `./gradlew build` (Loom plugin, Java 25, Minecraft 26.1.2) +- **Run Client**: `./gradlew runClient` (outputs to `run/` directory) +- **First Launch**: Creates `pupper.ok` config file and shows terms screen +- **Mod Initialization**: `ModManager.init()` registers all mods and settings + +## Project Conventions +- **Package**: `cn.pupperclient` with subpackages by feature (animation, event, gui, management, mixin, shader, skia, ui, utils) +- **Managers**: Singleton pattern for core systems (e.g., `EventBus.getInstance()`) +- **Events**: Extend `Event` class, post via `EventBus.getInstance().post(event)` +- **Mixins**: Located in `mixin/mixins/` with accessors in `mixin/interfaces/` +- **Dependencies**: Managed via `gradle/libs.versions.toml` version catalog +- **Resources**: Assets in `src/main/resources/assets/pupper/`, configs processed by Gradle + +## Integration Points +- **ViaFabricPlus**: Version protocol management via `PupperClient.getProtocolVersion()` +- **WebSocket**: Real-time communication in `management/websocket/` +- **Hypixel**: Server-specific features in `management/hypixel/` +- **Music**: MP3 playback with JLayer in `management/music/` +- **UI**: Custom GUI screens in `gui/`, HUD mods in `management/mod/impl/hud/` + +## Examples +- Add mod: Extend `Mod` class, register in `ModManager.initHudMods()` +- Handle event: Annotate method `@EventListener` or use `EventListener` +- Access Minecraft: Use mixins like `MixinMinecraftClient` for client modifications +- Add setting: Create `Setting` subclass, add via `ModManager.addSetting()` + diff --git a/LICENSE.md b/LICENSE.md index 91bfa39..b22b075 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,18 +1,7 @@ -# Pupper Client LICENSE -Version November 29, 2025 - -This License is GPL 3.0 - -The new license shall prevail. - -The original license is retained because Eldodebug opted for the MIT license, but it will have no effect. - - ## GPL 3.0 LICENSE -Version 3, 29 June 2025 +Copyright (C) 2026 Pupper Client -Copyright (C) 2007 Free Software Foundation, Inc. - +Version 3, 29 June 2025 Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. diff --git a/OLD_ELDODEBUG_LICENSE b/OLD_ELDODEBUG_LICENSE deleted file mode 100644 index 9a9c51c..0000000 --- a/OLD_ELDODEBUG_LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 Soar Client - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.MD b/README.MD deleted file mode 100644 index 65abbc4..0000000 --- a/README.MD +++ /dev/null @@ -1,45 +0,0 @@ -# Pupper Client - -A Better, Faster Minecraft Client for 1.21.4 - -## Features -- Optimized performance and gameplay experience -- Custom HUD and UI elements -- Built-in ViaFabricPlus for multi-version support -- In-game account switching capability -- Enhanced rendering and visual effects - -## Installation - -1. Download the mod from modrinth -2. Download the modpack from modrinth - -## Requirements -- **Minecraft**: 1.21.4 -- **Required Mods**: - - [IAS] In-Game Account Switcher - - ViaFabricPlus - - ModMenu - -## Download & Support - -**Official QQ Group**: 1023334402 - -**Developer Contacts**: -- oneachina - - QQ: 3565723760 - - Bilibili: https://space.bilibili.com/1582724340 - -**Official Links**: -- GitHub: https://github.com/PupperClient/ -- Fabric Version: https://github.com/PupperClient/Pupper-Client -- Neoforge Version: PupperClient/Pupper-Client-Neoforge (Coming Soon) -- Discord: https://discord.gg/8FbSHb7F - -## Notice -All resources are available in our official group files. Please download and use according to your needs. - ---- - -Pupper Client Official -2025/12/13 18:28 (Beijing time) diff --git a/README.md b/README.md new file mode 100644 index 0000000..961ba4f --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# Pupper Client + +A Better, Faster Minecraft Client + +## Features +- Optimized performance and gameplay experience +- Custom HUD and UI elements +- Built-in ViaFabricPlus for multi-version support +- In-game account switching capability +- Enhanced rendering and visual effects + +## Installation + +1. Ensure you have Fabric Loader version 0.18.6 or higher installed. +2. Download the latest version of Pupper Client from the [Modrinth](https://modrinth.com/mod/pupper-client) page. +3. Place the downloaded JAR file into your Minecraft `mods` folder. +4. Launch Minecraft with the Fabric Loader profile to enjoy the client. + +## Requirements +- **Minecraft** +- **Fabric Loader**: Version 0.18.6 or higher +- **Required Mods**: + - ViaFabricPlus + - ModMenu + +## License +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details + +## Contributing +Contributions are welcome! Please fork the repository and submit a pull request with your changes. + +For major changes, please open an issue first to discuss what you would like to change. diff --git a/build.gradle b/build.gradle deleted file mode 100644 index c29ab05..0000000 --- a/build.gradle +++ /dev/null @@ -1,145 +0,0 @@ -plugins { - id 'fabric-loom' version '1.14-SNAPSHOT' - id "me.modmuss50.mod-publish-plugin" version "1.1.0" -} - -project.ext.lwjglVersion = "3.3.3" -version = project.mod_version -group = project.maven_group - -base { - archivesName = project.archives_base_name -} - -loom { - accessWidenerPath = file("src/main/resources/pupper.accesswidener") -} - -repositories { - mavenCentral() - maven { url 'https://jitpack.io' } - maven { url "https://api.modrinth.com/maven" } - maven { url "https://maven.lenni0451.net/everything" } - maven { url "https://repo.viaversion.com/" } - maven { url "https://repo.opencollab.dev/maven-snapshots/" } - maven { url "https://maven.terraformersmc.com/" } - maven { url "https://maven.florianreuth.de/snapshots" } -} - -configurations { - jij - modJij - include.extendsFrom modJij - modImplementation.extendsFrom modJij -} - -dependencies { - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - - modImplementation "com.viaversion:viafabricplus-api:4.0.2" - modRuntimeOnly "maven.modrinth:sodium:mc1.21.4-0.6.6-fabric" - modRuntimeOnly "maven.modrinth:iris:1.8.5+1.21.4-fabric" - modRuntimeOnly "maven.modrinth:sodium-extra:mc1.21.4-0.6.1+fabric" - modRuntimeOnly "maven.modrinth:lithium:mc1.21.4-0.14.7-fabric" - modImplementation "maven.modrinth:in-game-account-switcher:WBbjirJP" - modImplementation "com.viaversion:viafabricplus:4.0.2" - modRuntimeOnly "maven.modrinth:immediatelyfast:1.3.3+1.21.4-fabric" - modRuntimeOnly "maven.modrinth:entityculling:NkBXk0Ye" - modImplementation "maven.modrinth:modmenu:13.0.3" - - jij 'io.github.smartboot.socket:aio-core:1.7.1' - jij 'com.github.ben-manes.caffeine:caffeine:3.1.8' - jij 'io.github.humbleui:types:0.2.0' - jij 'io.github.humbleui:skija-windows-x64:0.143.2' - jij 'io.github.humbleui:skija-linux-x64:0.143.2' - jij 'io.github.humbleui:skija-linux-arm64:0.143.2' - jij 'io.github.humbleui:skija-macos-x64:0.143.2' - jij 'com.kohlschutter.junixsocket:junixsocket-common:2.10.1' - jij 'org.java-websocket:Java-WebSocket:1.6.0' - jij 'com.mpatric:mp3agic:0.9.1' - jij 'javazoom:jlayer:1.0.1' - jij 'com.googlecode.soundlibs:mp3spi:1.9.5.4' - jij 'org:jaudiotagger:2.0.3' - jij 'com.googlecode.soundlibs:jlayer:1.0.1.4' - jij "net.lenni0451:MCPing:1.4.2" - jij "net.lenni0451:Reflect:1.4.0" - modImplementation 'net.java.dev.jna:jna:5.12.1' - modImplementation 'net.java.dev.jna:jna-platform:5.12.1' - - def lwjglNfdDeps = [ - "org.lwjgl:lwjgl-nfd:$lwjglVersion", - "org.lwjgl:lwjgl-nfd::natives-linux", - "org.lwjgl:lwjgl-nfd::natives-macos", - "org.lwjgl:lwjgl-nfd::natives-macos-arm64", - "org.lwjgl:lwjgl-nfd::natives-windows" - ] - - lwjglNfdDeps.each { dep -> - jij dep - implementation dep - include dep - } - - afterEvaluate { - configurations.jij.incoming.resolutionResult.allDependencies.each { - dependencies.include(dependencies.implementation(dependencies.compileOnlyApi(it.requested.toString()) { - transitive = false - })) - } - } -} - -processResources { - inputs.property "version", project.version - - filesMatching("fabric.mod.json") { - expand "version": project.version - } - - doLast { - def resourcePath = sourceSets.main.resources.srcDirs[0] - def iconFile = new File(resourcePath, "assets/pupper/logo.png") - if (!iconFile.exists()) { - throw new GradleException("Pupper icon not found: ${iconFile.absolutePath}") - } - } -} - -tasks.withType(JavaCompile).configureEach { - it.options.release = 21 -} - -java { - withSourcesJar() -} - -publishMods { - file = remapJar.archiveFile - changelog = providers.environmentVariable("CHANGELOG").getOrElse("No changelog provided") - type = STABLE - modLoaders.add("fabric") - - modrinth { - accessToken = providers.environmentVariable("MODRINTH_TOKEN") - projectId = "zN1WBfNk" - - minecraftVersions.add(project.minecraft_version) - - requires("fabric-api") - requires("viafabricplus") - requires("in-game-account-switcher") - requires("modmenu") - - optional("sodium", "iris") - } - - github { - accessToken = providers.environmentVariable("GITHUB_TOKEN") - repository = "PupperClient/Pupper-Client" - commitish = "main" - tagName = project.mod_version - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..5daab3c --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,134 @@ +plugins { + alias(libs.plugins.fabric.loom) +} + +val lwjglVersion = "3.4.1" + +val suffix: String = providers.gradleProperty("build_number").getOrElse("local") +version = "${libs.versions.minecraft.get()}-$suffix" +group = property("maven_group") as String +val minecraftVersion = property("minecraft_version") as String + +base { + archivesName = property("archives_base_name") as String +} + +loom { + accessWidenerPath = file("src/main/resources/pupper.classtweaker") + runs { + named("client") { + vmArgs.addAll( + listOf( + "-Xms512M", + "-Xmx4G", + "-XX:HeapBaseMinAddress=34g" + ) + ) + } + } +} + +repositories { + mavenCentral() + maven("https://jitpack.io") + maven("https://api.modrinth.com/maven") + maven("https://maven.lenni0451.net/everything") + maven("https://repo.viaversion.com/") + maven("https://repo.opencollab.dev/maven-snapshots/") + maven("https://maven.terraformersmc.com/") + maven("https://maven.florianreuth.de/snapshots") +} + +configurations { + create("modJij") + "include" { + extendsFrom(getByName("modJij")) + } + "implementation" { + extendsFrom(getByName("modJij")) + } +} + +dependencies { + // Minecraft & Fabric base + minecraft(libs.minecraft) + implementation(libs.fabric.loader) + implementation(libs.fabric.api) + + // Mod runtime + implementation(libs.viafabricplus.api) + runtimeOnly(libs.sodium) + runtimeOnly(libs.iris) + runtimeOnly(libs.lithium) + runtimeOnly(libs.immediatelyfast) + runtimeOnly(libs.entityculling) + runtimeOnly(libs.ias) + implementation(libs.modmenu) + implementation(libs.viafabricplus) + + // lib + "modJij"(libs.smartboot.aio) + "modJij"(libs.caffeine) + "modJij"(libs.humbleui.types) + "modJij"(libs.skija.windows) + "modJij"(libs.junixsocket.common) + "modJij"(libs.java.websocket) + "modJij"(libs.mp3agic) + "modJij"(libs.jlayer) + "modJij"(libs.mp3spi) + "modJij"(libs.jaudiotagger) + "modJij"(libs.jlayer.google) + "modJij"(libs.mcping) + "modJij"(libs.reflect) + + // JNA + implementation(libs.jna) + implementation(libs.jna.platform) + + // LWJGL NFD + "modJij"(libs.lwjgl.nfd) + + // LWJGL NFD Natives + val nfdNatives = listOf( + "natives-linux", + "natives-macos", + "natives-macos-arm64", + "natives-windows" + ) + nfdNatives.forEach { classifier -> + "modJij"("org.lwjgl:lwjgl-nfd:$lwjglVersion:$classifier") + } +} + +tasks.processResources { + inputs.property("version", project.version) + inputs.property("minecraft_version", minecraftVersion) + + filesMatching("fabric.mod.json") { + expand( + mapOf( + "version" to project.version, + "minecraft_version" to minecraftVersion + ) + ) + } + + doLast { + val resourcePath = sourceSets.main.get().resources.srcDirs.first() + val iconFile = File(resourcePath, "assets/pupper/logo.png") + if (!iconFile.exists()) { + throw GradleException("Pupper icon not found: ${iconFile.absolutePath}") + } + } +} + +tasks.withType().configureEach { + options.release = 25 +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(25) + } + withSourcesJar() +} diff --git a/gradle.properties b/gradle.properties index 172ab04..df2a37d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,17 +1,15 @@ -# Done to increase the memory available to gradle. org.gradle.jvmargs=-Xmx4G org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.4 -yarn_mappings=1.21.4+build.8 -loader_version=0.18.2 +minecraft_version=26.1.2 +loader_version=0.18.6 # Mod Properties -mod_version=26.1.1 +mod_version=26.4.1 maven_group=cn.pupperclient archives_base_name=pupper # Dependencies -fabric_version=0.119.4+1.21.4 +fabric_api_version=0.145.4+26.1.1 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..9b32e13 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,76 @@ +[versions] +# base +jdk = "25" +minecraft = "26.1.2" +fabric-loader = "0.18.6" +fabric-api = "0.145.4+26.1.2" + +# fabric +loom = "1.16-SNAPSHOT" + +# mod +sodium = "mc26.1.1-0.8.9-fabric" +lithium = "mc26.1.2-0.24.1-fabric" +iris = "1.10.9+26.1-fabric" +modmenu = "18.0.0-alpha.8" +viafabricplus = "4.5.2" +immediatelyfast = "1.15.2+26.1.2-fabric" +entityculling = "NaRJu6ah" +ias = "2ea1OpDg" + +# lib +lwjgl = "3.4.1" +smartboot-aio = "1.7.1" +caffeine = "3.1.8" +humbleui-types = "0.2.0" +skija-windows = "0.143.12" +junixsocket = "2.10.1" +java-websocket = "1.6.0" +mp3agic = "0.9.1" +jlayer = "1.0.1" +mp3spi = "1.9.5.4" +jaudiotagger = "2.0.3" +jlayer-google = "1.0.1.4" +mcping = "1.4.2" +reflect = "1.4.0" +jna = "5.12.1" + +[libraries] +# Fabric +minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } +fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" } +fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" } + +# mod +sodium = { module = "maven.modrinth:sodium", version.ref = "sodium" } +lithium = { module = "maven.modrinth:lithium", version.ref = "lithium" } +iris = { module = "maven.modrinth:iris", version.ref = "iris" } +modmenu = { module = "maven.modrinth:modmenu", version.ref = "modmenu" } +viafabricplus = { module = "com.viaversion:viafabricplus", version.ref = "viafabricplus" } +viafabricplus-api = { module = "com.viaversion:viafabricplus-api", version.ref = "viafabricplus" } +immediatelyfast = { module = "maven.modrinth:immediatelyfast", version.ref = "immediatelyfast" } +entityculling = { module = "maven.modrinth:entityculling", version.ref = "entityculling" } +ias = { module = "maven.modrinth:in-game-account-switcher", version.ref = "ias" } + +# lib +smartboot-aio = { module = "io.github.smartboot.socket:aio-core", version.ref = "smartboot-aio" } +caffeine = { module = "com.github.ben-manes.caffeine:caffeine", version.ref = "caffeine" } +humbleui-types = { module = "io.github.humbleui:types", version.ref = "humbleui-types" } +skija-windows = { module = "io.github.humbleui:skija-windows-x64", version.ref = "skija-windows" } +junixsocket-common = { module = "com.kohlschutter.junixsocket:junixsocket-common", version.ref = "junixsocket" } +java-websocket = { module = "org.java-websocket:Java-WebSocket", version.ref = "java-websocket" } +mp3agic = { module = "com.mpatric:mp3agic", version.ref = "mp3agic" } +jlayer = { module = "javazoom:jlayer", version.ref = "jlayer" } +mp3spi = { module = "com.googlecode.soundlibs:mp3spi", version.ref = "mp3spi" } +jaudiotagger = { module = "org:jaudiotagger", version.ref = "jaudiotagger" } +jlayer-google = { module = "com.googlecode.soundlibs:jlayer", version.ref = "jlayer-google" } +mcping = { module = "net.lenni0451:MCPing", version.ref = "mcping" } +reflect = { module = "net.lenni0451:Reflect", version.ref = "reflect" } +jna = { module = "net.java.dev.jna:jna", version.ref = "jna" } +jna-platform = { module = "net.java.dev.jna:jna-platform", version.ref = "jna" } + +# LWJGL NFD +lwjgl-nfd = { module = "org.lwjgl:lwjgl-nfd", version.ref = "lwjgl" } + +[plugins] +fabric-loom = { id = "net.fabricmc.fabric-loom", version.ref = "loom" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9..d997cfc 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 bad7c24..0ca609f 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.0-bin.zip +distributionUrl=https://mirrors.aliyun.com/macports/distfiles/gradle/gradle-9.4.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6..739907d 100644 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -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/2d6327017519d23b96af35865dc997fcb544fb40/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/. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a21..c4bdd3a 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 75c4d72..0000000 --- a/settings.gradle +++ /dev/null @@ -1,10 +0,0 @@ -pluginManagement { - repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - mavenCentral() - gradlePluginPortal() - } -} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..a7f3f56 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + maven { + name = "Fabric" + url = uri("https://maven.fabricmc.net/") + } + mavenCentral() + gradlePluginPortal() + } +} diff --git a/src/main/java/cn/pupperclient/PupperClient.java b/src/main/java/cn/pupperclient/PupperClient.java index 2ed43ad..a585bdb 100644 --- a/src/main/java/cn/pupperclient/PupperClient.java +++ b/src/main/java/cn/pupperclient/PupperClient.java @@ -3,7 +3,6 @@ import cn.pupperclient.animation.Delta; import cn.pupperclient.event.EventBus; import cn.pupperclient.event.server.PacketHandler; -import cn.pupperclient.gui.welcomegui.TermsScreen; import cn.pupperclient.management.cape.CapeManager; import cn.pupperclient.management.color.ColorManager; import cn.pupperclient.management.command.PupperCommand; @@ -19,10 +18,6 @@ import cn.pupperclient.utils.thread.Multithreading; import cn.pupperclient.utils.file.FileLocation; import cn.pupperclient.utils.language.*; -import com.viaversion.viafabricplus.ViaFabricPlus; -import com.viaversion.viafabricplus.api.ViaFabricPlusBase; -import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import org.apache.logging.log4j.Logger; import java.io.IOException; @@ -34,7 +29,8 @@ public class PupperClient implements IMinecraft { private static final String CONFIG_FILE_NAME = "pupper.ok"; private static final String ICON_PATH = "assets/pupper/logo.png"; private static final String CLIENT_NAME = "Pupper Client"; - private static final String CLIENT_VERSION = "26.1.1"; + private static final String CLIENT_VERSION = "mc26.1.2-9.0.0a"; + private static final String MOD_ID = "pupper"; private static final PupperClient INSTANCE = new PupperClient(); @@ -42,7 +38,6 @@ public class PupperClient implements IMinecraft { public static boolean firstLaunch = false; public static final Logger LOGGER = PupperLogger.getLogger(); - private final ViaFabricPlusBase viaPlatform = ViaFabricPlus.getImpl(); private long launchTime; private ModManager modManager; @@ -111,7 +106,6 @@ private void handleFirstLaunch() throws IOException { firstLaunch = true; createConfigFile(configFile); } - registerTermsScreenCheck(); } private void createConfigFile(Path configFile) throws IOException { @@ -128,15 +122,6 @@ private void createConfigFile(Path configFile) throws IOException { } } - private void registerTermsScreenCheck() { - ClientTickEvents.END_CLIENT_TICK.register(client -> { - if (firstLaunch && client.world != null && !hasAcceptedTerms) { - TermsScreen termsScreen = new TermsScreen(); - client.setScreen(termsScreen); - } - }); - } - private void checkResources() { if (getClass().getClassLoader().getResource(ICON_PATH) == null) { LOGGER.error("PupperClient icon not found in resources!"); @@ -193,15 +178,11 @@ public HypixelManager getHypixelManager() { return hypixelManager; } - public ProtocolVersion getProtocolVersion() { - return viaPlatform.getTargetVersion(); - } - - public void setProtocolVersion(ProtocolVersion version) { - viaPlatform.setTargetVersion(version); - } - public CapeManager getCapeManager() { return capeManager; } + + public static String getModId() { + return MOD_ID; + } } diff --git a/src/main/java/cn/pupperclient/PupperEventHandle.java b/src/main/java/cn/pupperclient/PupperEventHandle.java index 4e776d5..f874577 100644 --- a/src/main/java/cn/pupperclient/PupperEventHandle.java +++ b/src/main/java/cn/pupperclient/PupperEventHandle.java @@ -3,12 +3,9 @@ import java.util.List; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.EventListener; -import cn.pupperclient.event.EventType; import cn.pupperclient.event.client.*; import cn.pupperclient.event.server.impl.GameJoinEvent; import cn.pupperclient.management.profile.Profile; -import net.minecraft.client.MinecraftClient; public class PupperEventHandle { public final EventBus.EventListener onClientTick = event -> { diff --git a/src/main/java/cn/pupperclient/event/EventBus.java b/src/main/java/cn/pupperclient/event/EventBus.java index da0a806..c04a5c7 100644 --- a/src/main/java/cn/pupperclient/event/EventBus.java +++ b/src/main/java/cn/pupperclient/event/EventBus.java @@ -1,5 +1,7 @@ package cn.pupperclient.event; +import org.apache.logging.log4j.util.InternalApi; + import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; @@ -58,9 +60,9 @@ public void register(final Object object) { } } + @Deprecated private void registerFieldListeners(final Object object, List> handlers) { for (final Field field : getCachedDeclaredFields(object.getClass())) { - // 修改这里:使用 EventListener 而不是 EventListener if (field.getType() == EventListener.class) { final EventListener eventListener = getEventHandler(object, field); if (eventListener != null) { @@ -96,9 +98,6 @@ private void registerMethodListeners(final Object object, List> } } - /** - * 注册单个监听器到映射中 - */ private void registerListener(Type eventType, EventListener listener) { listenerMap.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>()).add(listener); sortCallback.accept(listenerMap.get(eventType), priorityOrder); diff --git a/src/main/java/cn/pupperclient/event/EventListener.java b/src/main/java/cn/pupperclient/event/EventListener.java index 081f131..3a5fdc4 100644 --- a/src/main/java/cn/pupperclient/event/EventListener.java +++ b/src/main/java/cn/pupperclient/event/EventListener.java @@ -8,5 +8,23 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface EventListener { - int priority() default 0; + Priority priority() default Priority.NORMAL; + + enum Priority { + LOWEST(-100), + LOW(-50), + NORMAL(0), + HIGH(50), + HIGHEST(1001); + + private final int value; + + Priority(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } } diff --git a/src/main/java/cn/pupperclient/event/MethodEventListener.java b/src/main/java/cn/pupperclient/event/MethodEventListener.java index 6615b5b..d81d52b 100644 --- a/src/main/java/cn/pupperclient/event/MethodEventListener.java +++ b/src/main/java/cn/pupperclient/event/MethodEventListener.java @@ -15,7 +15,7 @@ public MethodEventListener(Object target, Method method) { this.eventType = (Class) method.getParameterTypes()[0]; EventListener annotation = method.getAnnotation(EventListener.class); - this.priority = annotation != null ? annotation.priority() : 0; + this.priority = annotation != null ? annotation.priority().getValue() : 0; if (!method.canAccess(target)) { method.setAccessible(true); diff --git a/src/main/java/cn/pupperclient/event/client/DrawItemHotbarEvent.java b/src/main/java/cn/pupperclient/event/client/DrawItemHotbarEvent.java new file mode 100644 index 0000000..f9fe0a7 --- /dev/null +++ b/src/main/java/cn/pupperclient/event/client/DrawItemHotbarEvent.java @@ -0,0 +1,10 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.event.client; + +import cn.pupperclient.event.Event; + +public class DrawItemHotbarEvent extends Event { +} diff --git a/src/main/java/cn/pupperclient/event/client/ReceivePacketEvent.java b/src/main/java/cn/pupperclient/event/client/ReceivePacketEvent.java index 78537b5..280b59c 100644 --- a/src/main/java/cn/pupperclient/event/client/ReceivePacketEvent.java +++ b/src/main/java/cn/pupperclient/event/client/ReceivePacketEvent.java @@ -1,8 +1,7 @@ package cn.pupperclient.event.client; import cn.pupperclient.event.Event; - -import net.minecraft.network.packet.Packet; +import net.minecraft.network.protocol.Packet; public class ReceivePacketEvent extends Event { diff --git a/src/main/java/cn/pupperclient/event/client/RenderGameOverlayEvent.java b/src/main/java/cn/pupperclient/event/client/RenderGameOverlayEvent.java index 7934144..e9f556c 100644 --- a/src/main/java/cn/pupperclient/event/client/RenderGameOverlayEvent.java +++ b/src/main/java/cn/pupperclient/event/client/RenderGameOverlayEvent.java @@ -1,18 +1,17 @@ package cn.pupperclient.event.client; import cn.pupperclient.event.Event; - -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.GuiGraphicsExtractor; public class RenderGameOverlayEvent extends Event { - private final DrawContext context; + private final GuiGraphicsExtractor context; - public RenderGameOverlayEvent(DrawContext context) { + public RenderGameOverlayEvent(GuiGraphicsExtractor context) { this.context = context; } - public DrawContext getContext() { + public GuiGraphicsExtractor getContext() { return context; } } diff --git a/src/main/java/cn/pupperclient/event/client/ResolutionChangedEvent.java b/src/main/java/cn/pupperclient/event/client/ResolutionChangedEvent.java new file mode 100644 index 0000000..1817a1e --- /dev/null +++ b/src/main/java/cn/pupperclient/event/client/ResolutionChangedEvent.java @@ -0,0 +1,9 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.event.client; + +import cn.pupperclient.event.Event; + +public class ResolutionChangedEvent extends Event {} diff --git a/src/main/java/cn/pupperclient/event/client/SendPacketEvent.java b/src/main/java/cn/pupperclient/event/client/SendPacketEvent.java index 4cf477d..210dda5 100644 --- a/src/main/java/cn/pupperclient/event/client/SendPacketEvent.java +++ b/src/main/java/cn/pupperclient/event/client/SendPacketEvent.java @@ -1,8 +1,7 @@ package cn.pupperclient.event.client; import cn.pupperclient.event.Event; - -import net.minecraft.network.packet.Packet; +import net.minecraft.network.protocol.Packet; public class SendPacketEvent extends Event { diff --git a/src/main/java/cn/pupperclient/event/client/TotemEvent.java b/src/main/java/cn/pupperclient/event/client/TotemEvent.java index 5053d45..5ef7f2e 100644 --- a/src/main/java/cn/pupperclient/event/client/TotemEvent.java +++ b/src/main/java/cn/pupperclient/event/client/TotemEvent.java @@ -1,16 +1,16 @@ package cn.pupperclient.event.client; import cn.pupperclient.event.Event; -import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.world.entity.player.Player; public class TotemEvent extends Event { - private final PlayerEntity player; + private final Player player; - public TotemEvent(PlayerEntity entity) { + public TotemEvent(Player entity) { player = entity; } - public PlayerEntity getPlayer() { + public Player getPlayer() { return player; } } diff --git a/src/main/java/cn/pupperclient/event/server/PacketHandler.java b/src/main/java/cn/pupperclient/event/server/PacketHandler.java index 1da2921..278ca6f 100644 --- a/src/main/java/cn/pupperclient/event/server/PacketHandler.java +++ b/src/main/java/cn/pupperclient/event/server/PacketHandler.java @@ -1,6 +1,7 @@ package cn.pupperclient.event.server; import cn.pupperclient.event.EventBus; +import cn.pupperclient.event.EventListener; import cn.pupperclient.event.client.ReceivePacketEvent; import cn.pupperclient.event.client.SendPacketEvent; import cn.pupperclient.event.server.impl.AttackEntityEvent; @@ -8,38 +9,27 @@ import cn.pupperclient.event.server.impl.GameJoinEvent; import cn.pupperclient.event.server.impl.ReceiveChatEvent; import cn.pupperclient.event.server.impl.SendChatEvent; -import cn.pupperclient.mixin.mixins.minecraft.network.packet.PlayerInteractEntityC2SPacketAccessor; - -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket; -import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; -import net.minecraft.network.packet.s2c.play.ChatMessageS2CPacket; -import net.minecraft.network.packet.s2c.play.EntityDamageS2CPacket; -import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; -import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.*; public class PacketHandler { - public final EventBus.EventListener onSendPacket = packetEvent -> { + @EventListener + public void onSendPacket(SendPacketEvent packetEvent) { Packet basePacket = packetEvent.getPacket(); - if (basePacket instanceof PlayerInteractEntityC2SPacket) { - - PlayerInteractEntityC2SPacket packet = (PlayerInteractEntityC2SPacket) basePacket; - PlayerInteractEntityC2SPacket.InteractType type = ((PlayerInteractEntityC2SPacketAccessor) packet) - .getInteractTypeHandler().getType(); + if (basePacket instanceof ServerboundInteractPacket packet) { - if (type.equals(PlayerInteractEntityC2SPacket.InteractType.ATTACK)) { + if (!packet.usingSecondaryAction()) { EventBus.getInstance() - .post(new AttackEntityEvent(((PlayerInteractEntityC2SPacketAccessor) packet).entityId())); + .post(new AttackEntityEvent((packet.entityId()))); } } - if (basePacket instanceof ChatMessageC2SPacket) { + if (basePacket instanceof ServerboundChatPacket packet) { - ChatMessageC2SPacket packet = (ChatMessageC2SPacket) basePacket; - SendChatEvent event = new SendChatEvent(packet.chatMessage()); + SendChatEvent event = new SendChatEvent(packet.message()); EventBus.getInstance().post(event); @@ -49,21 +39,19 @@ public class PacketHandler { } }; - public final EventBus.EventListener onReceivePacket = packetEvent -> { + @EventListener + public void onReceivePacket(ReceivePacketEvent packetEvent) { Packet basePacket = packetEvent.getPacket(); - if (basePacket instanceof EntityDamageS2CPacket) { - - EntityDamageS2CPacket packet = (EntityDamageS2CPacket) basePacket; + if (basePacket instanceof ClientboundDamageEventPacket packet) { - EventBus.getInstance().post(new DamageEntityEvent(packet.entityId())); + EventBus.getInstance().post(new DamageEntityEvent(packet.entityId())); } - if (basePacket instanceof ChatMessageS2CPacket) { + if (basePacket instanceof ClientboundPlayerChatPacket packet) { - ChatMessageS2CPacket packet = (ChatMessageS2CPacket) basePacket; - ReceiveChatEvent event = new ReceiveChatEvent(packet.body().content()); + ReceiveChatEvent event = new ReceiveChatEvent(packet.body().content()); EventBus.getInstance().post(event); @@ -72,10 +60,9 @@ public class PacketHandler { } } - if (basePacket instanceof GameMessageS2CPacket) { + if (basePacket instanceof ClientboundSystemChatPacket packet) { - GameMessageS2CPacket packet = (GameMessageS2CPacket) basePacket; - ReceiveChatEvent event = new ReceiveChatEvent(packet.content().getString()); + ReceiveChatEvent event = new ReceiveChatEvent(packet.content().getString()); EventBus.getInstance().post(event); @@ -84,7 +71,7 @@ public class PacketHandler { } } - if (basePacket instanceof GameJoinS2CPacket) { + if (basePacket instanceof ClientboundLoginPacket) { EventBus.getInstance().post(new GameJoinEvent()); } }; diff --git a/src/main/java/cn/pupperclient/event/skia/DrawSkiaEvent.java b/src/main/java/cn/pupperclient/event/skia/DrawSkiaEvent.java new file mode 100644 index 0000000..5854e17 --- /dev/null +++ b/src/main/java/cn/pupperclient/event/skia/DrawSkiaEvent.java @@ -0,0 +1,20 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.event.skia; + +import cn.pupperclient.event.Event; +import io.github.humbleui.skija.Canvas; + +public class DrawSkiaEvent extends Event { + private final Canvas canvas; + + public DrawSkiaEvent(Canvas canvas) { + this.canvas = canvas; + } + + public Canvas getCanvas() { + return canvas; + } +} diff --git a/src/main/java/cn/pupperclient/event/client/RenderSkiaEvent.java b/src/main/java/cn/pupperclient/event/skia/RenderSkiaEvent.java similarity index 67% rename from src/main/java/cn/pupperclient/event/client/RenderSkiaEvent.java rename to src/main/java/cn/pupperclient/event/skia/RenderSkiaEvent.java index a544594..bfb3bf8 100644 --- a/src/main/java/cn/pupperclient/event/client/RenderSkiaEvent.java +++ b/src/main/java/cn/pupperclient/event/skia/RenderSkiaEvent.java @@ -1,7 +1,9 @@ -package cn.pupperclient.event.client; +package cn.pupperclient.event.skia; import cn.pupperclient.event.Event; +import cn.pupperclient.skia.api.WrappedBackendRenderTarget; import io.github.humbleui.skija.Canvas; +import io.github.humbleui.skija.DirectContext; public class RenderSkiaEvent extends Event { private final Canvas canvas; diff --git a/src/main/java/cn/pupperclient/gui/GuiResourcePackConvert.java b/src/main/java/cn/pupperclient/gui/GuiResourcePackConvert.java index 7a32b25..d0289fc 100644 --- a/src/main/java/cn/pupperclient/gui/GuiResourcePackConvert.java +++ b/src/main/java/cn/pupperclient/gui/GuiResourcePackConvert.java @@ -13,6 +13,7 @@ import java.util.zip.ZipInputStream; import cn.pupperclient.PupperClient; +import cn.pupperclient.utils.minecraft.interfaces.IMinecraft; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import cn.pupperclient.libraries.resourcepack.ResourcePackConverter; @@ -21,18 +22,18 @@ import cn.pupperclient.utils.file.FileLocation; import it.unimi.dsi.fastutil.objects.ObjectObjectImmutablePair; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.Text; -import net.minecraft.util.Colors; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.util.CommonColors; -public class GuiResourcePackConvert extends Screen { +public class GuiResourcePackConvert extends Screen implements IMinecraft { private String progress = "Converting..."; private Screen prevScreen; public GuiResourcePackConvert(Screen prevScreen) { - super(Text.of("PackConvert")); + super(Component.literal("PackConvert")); this.prevScreen = prevScreen; } @@ -45,17 +46,15 @@ public void init() { } catch (Exception e) { PupperClient.LOGGER.error("converter error: {}", e.getMessage()); } - if (client != null) { - client.setScreen(prevScreen); - } + client.setScreen(prevScreen); }); super.init(); } @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); - context.drawCenteredTextWithShadow(this.textRenderer, Text.of(progress), this.width / 2, this.height / 2 - 50, Colors.WHITE); + public void extractRenderState(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { + super.extractRenderState(context, mouseX, mouseY, delta); + context.text(this.font, Component.literal(progress), this.width / 2, this.height / 2 - 50, CommonColors.WHITE); } private ResourcePackConverter createConverter() { @@ -74,7 +73,7 @@ private ResourcePackConverter createConverter() { try { File targetFile = new File(cacheDir, f.getName()); - File packDir = new File(client.runDirectory, "resourcepacks"); + File packDir = new File(client.gameDirectory, "resourcepacks"); File outputFile = new File(packDir, f.getName()); Files.move(f.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); @@ -132,7 +131,7 @@ private List detectPacks() { private List getOldResourcePacks() { List files = new ArrayList<>(); - File packDir = new File(client.runDirectory, "resourcepacks"); + File packDir = new File(client.gameDirectory, "resourcepacks"); File[] packFiles = packDir.listFiles(); if (packFiles != null) { diff --git a/src/main/java/cn/pupperclient/gui/MainMenuGui.java b/src/main/java/cn/pupperclient/gui/MainMenuGui.java deleted file mode 100644 index d922215..0000000 --- a/src/main/java/cn/pupperclient/gui/MainMenuGui.java +++ /dev/null @@ -1,664 +0,0 @@ -package cn.pupperclient.gui; - -import java.util.ArrayList; -import java.util.List; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; - -import cn.pupperclient.PupperClient; -import com.google.gson.JsonObject; -import cn.pupperclient.animation.SimpleAnimation; -import cn.pupperclient.gui.api.SimpleSoarGui; -import cn.pupperclient.management.color.api.ColorPalette; -import cn.pupperclient.management.config.ConfigType; -import cn.pupperclient.management.mod.impl.settings.ModMenuSettings; -import cn.pupperclient.skia.Skia; -import cn.pupperclient.skia.font.Fonts; -import cn.pupperclient.skia.font.Icon; -import cn.pupperclient.ui.component.api.PressAnimation; -import cn.pupperclient.ui.component.impl.Button; -import cn.pupperclient.ui.component.impl.IconButton; -import cn.pupperclient.ui.component.impl.Switch; -import cn.pupperclient.ui.component.handler.impl.ButtonHandler; -import cn.pupperclient.ui.component.handler.impl.SwitchHandler; -import cn.pupperclient.utils.color.ColorUtils; -import cn.pupperclient.utils.language.I18n; -import cn.pupperclient.utils.mouse.MouseUtils; -import cn.pupperclient.utils.thread.Multithreading; -import cn.pupperclient.utils.file.FileDialog; -import cn.pupperclient.utils.file.FileLocation; -import cn.pupperclient.utils.mouse.ScrollHelper; -import com.terraformersmc.modmenu.gui.ModsScreen; -import it.unimi.dsi.fastutil.objects.ObjectObjectImmutablePair; - -import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; -import net.minecraft.client.gui.screen.option.OptionsScreen; -import net.minecraft.client.gui.screen.world.SelectWorldScreen; -import net.minecraft.client.realms.gui.screen.RealmsMainScreen; -import net.minecraft.client.MinecraftClient; -import ru.vidtu.ias.screen.AccountScreen; - -public class MainMenuGui extends SimpleSoarGui { - - private final List buttons = new ArrayList<>(); - private MainMenuButton settingsButton; - private MainMenuButton backgroundButton; - private boolean showCustomizationWindow = false; - private boolean showBackgroundWindow = false; - private Switch darkModeSwitch; - private Button exitCustomizationButton; - private Button exitBackgroundButton; - private IconButton addBackgroundButton; - private final List backgroundItems = new ArrayList<>(); - private String selectedBackgroundId = "background.png"; - private final ScrollHelper backgroundScrollHelper = new ScrollHelper(); - private float parallaxX = 0; - private float parallaxY = 0; - - public MainMenuGui() { - super(false); - } - - @Override - public void init() { - loadBackgroundSettings(); - rebuildLayout(); - loadExistingBackgrounds(); - } - - @Override - public void resize(MinecraftClient client, int width, int height) { - super.resize(client, width, height); - rebuildLayout(); - } - - private void loadBackgroundSettings() { - JsonObject config = PupperClient.getInstance().getConfigManager().getConfig(ConfigType.MOD).getJsonObject(); - try { - if (config.has("mainmenu.background")) { - selectedBackgroundId = config.get("mainmenu.background").getAsString(); - } - } catch (Exception e) { - selectedBackgroundId = "background.png"; - } - } - - private void saveBackgroundSettings() { - JsonObject config = PupperClient.getInstance().getConfigManager().getConfig(ConfigType.MOD).getJsonObject(); - config.addProperty("mainmenu.background", selectedBackgroundId); - PupperClient.getInstance().getConfigManager().save(ConfigType.MOD); - } - - private void rebuildLayout() { - buttons.clear(); - - float scaleFactor = calculateScaleFactor(); - - float centerX = client.getWindow().getWidth() / 2f; - float centerY = client.getWindow().getHeight() / 2f; - float buttonWidth = 240 * scaleFactor; - - buttons.add(new MainMenuButton("menu.singleplayer", Icon.HOME, - centerX - buttonWidth / 2, centerY - (120 * scaleFactor), buttonWidth, scaleFactor, () -> client.setScreen(new SelectWorldScreen(this)))); - - buttons.add(new MainMenuButton("menu.multiplayer", Icon.GROUPS, - centerX - buttonWidth / 2, centerY - (60 * scaleFactor), buttonWidth, scaleFactor, () -> { - client.setScreen(new MultiplayerScreen(this)); - })); - - buttons.add(new MainMenuButton("menu.realms", Icon.DNS, - centerX - buttonWidth / 2, centerY, buttonWidth, scaleFactor, () -> client.setScreen(new RealmsMainScreen(this)))); - - buttons.add(new MainMenuButton("menu.ias", Icon.ACCOUNT_BALANCE, - centerX - buttonWidth / 2, centerY + (60 * scaleFactor), buttonWidth, scaleFactor, () -> client.setScreen(new AccountScreen(this)))); - - buttons.add(new MainMenuButton("menu.modmenu", Icon.LIST, - centerX - buttonWidth / 2, centerY + (120 * scaleFactor), buttonWidth, scaleFactor, () -> client.setScreen(new ModsScreen(this)))); - - buttons.add(new MainMenuButton("menu.options", Icon.SETTINGS, - centerX - buttonWidth / 2, centerY + (180 * scaleFactor), buttonWidth, scaleFactor, () -> client.setScreen(new OptionsScreen(this, client.options)))); - - buttons.add(new MainMenuButton("menu.quit", Icon.CLOSE, - centerX - buttonWidth / 2, centerY + (240 * scaleFactor), buttonWidth, scaleFactor, () -> client.scheduleStop())); - - float buttonSize = 40 * scaleFactor; - float buttonSpacing = 10 * scaleFactor; - - backgroundButton = new MainMenuButton("", Icon.IMAGE, - client.getWindow().getWidth() - (buttonSize * 2) - buttonSpacing - (20 * scaleFactor), - 20 * scaleFactor, buttonSize, scaleFactor, () -> showBackgroundWindow = true); - - settingsButton = new MainMenuButton("", Icon.SETTINGS, - client.getWindow().getWidth() - buttonSize - (20 * scaleFactor), - 20 * scaleFactor, buttonSize - 5, scaleFactor, () -> showCustomizationWindow = true); - - for (MainMenuButton button : buttons) { - button.setEnabled(true); - } - - initCustomizationComponents(); - } - - private void initCustomizationComponents() { - float centerX = client.getWindow().getWidth() / 2f; - float centerY = client.getWindow().getHeight() / 2f; - float panelWidth = 450; - float panelX = centerX - panelWidth / 2; - - darkModeSwitch = new Switch(panelX + panelWidth - 72, centerY - 50, ModMenuSettings.getInstance().getDarkModeSetting().isEnabled()); - darkModeSwitch.setHandler(new SwitchHandler() { - @Override - public void onEnabled() { - ModMenuSettings.getInstance().getDarkModeSetting().setEnabled(true); - } - - @Override - public void onDisabled() { - ModMenuSettings.getInstance().getDarkModeSetting().setEnabled(false); - } - }); - - exitCustomizationButton = new Button("gui.done", centerX - 50, centerY + 50, Button.Style.TONAL); - exitCustomizationButton.setHandler(new ButtonHandler() { - @Override - public void onAction() { - showCustomizationWindow = false; - } - }); - - float backgroundPanelWidth = 600; - float backgroundPanelHeight = 400; - float backgroundPanelX = centerX - backgroundPanelWidth / 2; - float backgroundPanelY = centerY - backgroundPanelHeight / 2; - - exitBackgroundButton = new Button("gui.done", centerX - 50, backgroundPanelY + backgroundPanelHeight - 60, Button.Style.TONAL); - exitBackgroundButton.setHandler(new ButtonHandler() { - @Override - public void onAction() { - showBackgroundWindow = false; - } - }); - - addBackgroundButton = new IconButton(Icon.ADD, - backgroundPanelX + backgroundPanelWidth - 70, - backgroundPanelY + backgroundPanelHeight - 70, - IconButton.Size.NORMAL, - IconButton.Style.PRIMARY); - addBackgroundButton.setHandler(new ButtonHandler() { - @Override - public void onAction() { - Multithreading.runAsync(() -> { - ObjectObjectImmutablePair result = FileDialog.chooseFile("Select Background Image", "png", "jpg"); - - if (result.left()) { - File selectedFile = result.right(); - copyBackgroundFile(selectedFile); - } - }); - } - }); - } - - private void loadExistingBackgrounds() { - backgroundItems.clear(); - - backgroundItems.add(new BackgroundItem("background.png", null, true)); - - File backgroundDir = FileLocation.BACKGROUND_DIR; - if (!backgroundDir.exists()) { - backgroundDir.mkdirs(); - } - if (backgroundDir.exists() && backgroundDir.isDirectory()) { - File[] backgroundFiles = backgroundDir.listFiles((dir, name) -> - name.toLowerCase().endsWith(".png") || name.toLowerCase().endsWith(".jpg")); - if (backgroundFiles != null) { - for (File backgroundFile : backgroundFiles) { - String backgroundId = backgroundFile.getName(); - backgroundItems.add(new BackgroundItem(backgroundId, backgroundFile, false)); - } - } - } - } - - private void copyBackgroundFile(File selectedFile) { - try { - String originalName = selectedFile.getName(); - String processedName = originalName.replace(" ", "_"); - File targetFile = new File(FileLocation.BACKGROUND_DIR, processedName); - - if (targetFile.exists()) { - PupperClient.LOGGER.warn("background file already exists: {}", processedName); - return; - } - - Files.copy(selectedFile.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - client.execute(() -> { - loadExistingBackgrounds(); - selectedBackgroundId = processedName; - saveBackgroundSettings(); - }); - - } catch (IOException e) { - PupperClient.LOGGER.error("Error copying background file: {}", e.getMessage(), e); - } - } - - private boolean isWindowMinimized() { - return client.getWindow().getWidth() < 100 || client.getWindow().getHeight() < 100; - } - - private float calculateScaleFactor() { - float currentWidth = client.getWindow().getWidth(); - float currentHeight = client.getWindow().getHeight(); - - if (isWindowMinimized()) { - return 0.5f; - } - - float windowArea = currentWidth * currentHeight; - - if (windowArea < 800 * 600) { - return 1.4f; - } else if (windowArea < 1280 * 720) { - return 1.2f; - } else if (windowArea < 1920 * 1080) { - return 1.0f; - } else { - return 0.9f; - } - } - - @Override - public void draw(double mouseX, double mouseY) { - if (isWindowMinimized()) { - return; - } - - PupperClient instance = PupperClient.getInstance(); - ColorPalette palette = instance.getColorManager().getPalette(); - - drawCustomBackground(); - drawLogoIcon(); - - for (MainMenuButton button : buttons) { - button.draw((int) mouseX, (int) mouseY); - } - - backgroundButton.draw((int) mouseX, (int) mouseY); - settingsButton.draw((int) mouseX, (int) mouseY); - - if (showCustomizationWindow) { - drawCustomizationWindow(mouseX, mouseY, palette); - } - - if (showBackgroundWindow) { - drawBackgroundWindow(mouseX, mouseY, palette); - } - } - - private void drawCustomizationWindow(double mouseX, double mouseY, ColorPalette palette) { - float centerX = client.getWindow().getWidth() / 2f; - float centerY = client.getWindow().getHeight() / 2f; - float panelWidth = 450; - float panelHeight = 200; - float panelX = centerX - panelWidth / 2; - float panelY = centerY - panelHeight / 2; - - Skia.drawRect(0, 0, client.getWindow().getWidth(), client.getWindow().getHeight(), - ColorUtils.applyAlpha(palette.getSurface(), 0.3f)); - - Skia.drawRoundedRect(panelX, panelY, panelWidth, panelHeight, 20, palette.getSurfaceContainer()); - - Skia.drawCenteredText(I18n.get("gui.mainmenu.customization"), centerX, panelY + 25, - palette.getOnSurface(), Fonts.getRegular(20)); - - Skia.drawText(I18n.get("setting.darkmode"), panelX + 20, centerY - 35, - palette.getOnSurface(), Fonts.getRegular(16)); - - darkModeSwitch.draw(mouseX, mouseY); - exitCustomizationButton.draw(mouseX, mouseY); - } - - private void drawBackgroundWindow(double mouseX, double mouseY, ColorPalette palette) { - float centerX = client.getWindow().getWidth() / 2f; - float centerY = client.getWindow().getHeight() / 2f; - float panelWidth = 600; - float panelHeight = 400; - float panelX = centerX - panelWidth / 2; - float panelY = centerY - panelHeight / 2; - - backgroundScrollHelper.onUpdate(); - - Skia.drawRect(0, 0, client.getWindow().getWidth(), client.getWindow().getHeight(), - ColorUtils.applyAlpha(palette.getSurface(), 0.3f)); - - Skia.drawRoundedRect(panelX, panelY, panelWidth, panelHeight, 20, palette.getSurfaceContainer()); - - Skia.drawText(I18n.get("setting.background"), panelX + 20, panelY + 30, - palette.getOnSurface(), Fonts.getRegular(20)); - - double adjustedMouseY = mouseY - backgroundScrollHelper.getValue(); - - Skia.save(); - Skia.translate(0, backgroundScrollHelper.getValue()); - - float startX = panelX + 20; - float startY = panelY + 60; - float itemWidth = 160; - float itemHeight = 90; - float spacing = 15; - int itemsPerRow = 3; - - for (int i = 0; i < backgroundItems.size(); i++) { - BackgroundItem item = backgroundItems.get(i); - - int row = i / itemsPerRow; - int col = i % itemsPerRow; - - float itemX = startX + col * (itemWidth + spacing); - float itemY = startY + row * (itemHeight + spacing); - - item.xAnimation.onTick(itemX, 14); - item.yAnimation.onTick(itemY, 14); - - itemX = item.xAnimation.getValue(); - itemY = item.yAnimation.getValue(); - - boolean isSelected = item.backgroundId.equals(selectedBackgroundId); - boolean isHovered = MouseUtils.isInside(mouseX, adjustedMouseY, itemX, itemY, itemWidth, itemHeight); - - item.focusAnimation.onTick(isHovered ? 1 : 0, 10); - - java.awt.Color bgColor = palette.getSurface(); - Skia.drawRoundedRect(itemX, itemY, itemWidth, itemHeight, 8, bgColor); - - if (isSelected) { - Skia.drawOutline(itemX - 2, itemY - 2, itemWidth + 4, itemHeight + 4, 10, 3, palette.getPrimary()); - } - - if (!isSelected && isHovered) { - Skia.drawRoundedRect(itemX, itemY, itemWidth, itemHeight, 8, - ColorUtils.applyAlpha(palette.getPrimary(), item.focusAnimation.getValue() * 0.12f)); - } - - if (item.isDefault) { - Skia.drawRoundedImage("background.png", itemX, itemY, itemWidth, itemHeight, 8); - } else if (item.backgroundFile != null && item.backgroundFile.exists()) { - Skia.drawRoundedImage(item.backgroundFile, itemX, itemY, itemWidth, itemHeight, 8); - } - } - - int totalRows = (int) Math.ceil((double) backgroundItems.size() / itemsPerRow); - float totalHeight = totalRows * (itemHeight + spacing); - backgroundScrollHelper.setMaxScroll(totalHeight, panelHeight - 120); - - Skia.restore(); - - exitBackgroundButton.draw(mouseX, mouseY); - addBackgroundButton.draw(mouseX, mouseY); - } - - private void drawCustomBackground() { - float parallaxStrength = 40; - float targetParallaxX = (float) (client.mouse.getX() - client.getWindow().getWidth() / 2F) / client.getWindow().getWidth() * parallaxStrength; - float targetParallaxY = (float) (client.mouse.getY() - client.getWindow().getHeight() / 2F) / client.getWindow().getHeight() * parallaxStrength; - - parallaxX += (targetParallaxX - parallaxX) * 0.1f; - parallaxY += (targetParallaxY - parallaxY) * 0.1f; - - float backgroundScale = 1.2f; - float scaledWidth = client.getWindow().getWidth() * backgroundScale; - float scaledHeight = client.getWindow().getHeight() * backgroundScale; - - float offsetX = (scaledWidth - client.getWindow().getWidth()) / 2 - parallaxX; - float offsetY = (scaledHeight - client.getWindow().getHeight()) / 2 - parallaxY; - - if (selectedBackgroundId.equals("background.png")) { - Skia.drawImage("background.png", -offsetX, -offsetY, scaledWidth, scaledHeight); - } else { - for (BackgroundItem item : backgroundItems) { - if (item.backgroundId.equals(selectedBackgroundId) && !item.isDefault) { - if (item.backgroundFile != null && item.backgroundFile.exists()) { - Skia.drawImage(item.backgroundFile, -offsetX, -offsetY, scaledWidth, scaledHeight); - return; - } - } - } - Skia.drawImage("background.png", -offsetX, -offsetY, scaledWidth, scaledHeight); - } - } - - private void drawLogoIcon() { - float scaleFactor = calculateScaleFactor(); - float logoSize = 170 * scaleFactor + 25; - float logoX = client.getWindow().getWidth() / 2f - logoSize / 2; - - float centerY = client.getWindow().getHeight() / 2f; - float singleplayerButtonY = centerY - (120 * scaleFactor); - float logoY = singleplayerButtonY - logoSize - (1 * scaleFactor); - - Skia.drawRoundedImage("logo.png", logoX, logoY, logoSize, logoSize, 10 * scaleFactor); - } - - @Override - public boolean onMouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { - if (showBackgroundWindow) { - backgroundScrollHelper.onScroll(verticalAmount); - return true; - } - return super.onMouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); - } - - @Override - public boolean onMousePressed(double mouseX, double mouseY, int button) { - if (isWindowMinimized()) { - return false; - } - - if (showBackgroundWindow) { - exitBackgroundButton.mousePressed(mouseX, mouseY, button); - addBackgroundButton.mousePressed(mouseX, mouseY, button); - - float adjustedMouseY = (float) (mouseY - backgroundScrollHelper.getValue()); - float panelX = client.getWindow().getWidth() / 2f - 300; - float panelY = client.getWindow().getHeight() / 2f - 200; - float startX = panelX + 20; - float startY = panelY + 60; - float itemWidth = 160; - float itemHeight = 90; - float spacing = 15; - int itemsPerRow = 3; - - for (int i = 0; i < backgroundItems.size(); i++) { - BackgroundItem item = backgroundItems.get(i); - int row = i / itemsPerRow; - int col = i % itemsPerRow; - float itemX = startX + col * (itemWidth + spacing); - float itemY = startY + row * (itemHeight + spacing); - - if (MouseUtils.isInside(mouseX, adjustedMouseY, itemX, itemY, itemWidth, itemHeight)) { - selectedBackgroundId = item.backgroundId; - saveBackgroundSettings(); - break; - } - } - return true; - } - - if (showCustomizationWindow) { - darkModeSwitch.mousePressed(mouseX, mouseY, button); - exitCustomizationButton.mousePressed(mouseX, mouseY, button); - return true; - } - - for (MainMenuButton menuButton : buttons) { - menuButton.mousePressed((int) mouseX, (int) mouseY, button); - } - - backgroundButton.mousePressed((int) mouseX, (int) mouseY, button); - settingsButton.mousePressed((int) mouseX, (int) mouseY, button); - return true; - } - - @Override - public boolean onMouseReleased(double mouseX, double mouseY, int button) { - if (isWindowMinimized()) { - return false; - } - - if (showBackgroundWindow) { - exitBackgroundButton.mouseReleased(mouseX, mouseY, button); - addBackgroundButton.mouseReleased(mouseX, mouseY, button); - return true; - } - - if (showCustomizationWindow) { - darkModeSwitch.mouseReleased(mouseX, mouseY, button); - exitCustomizationButton.mouseReleased(mouseX, mouseY, button); - return true; - } - - for (MainMenuButton menuButton : buttons) { - menuButton.mouseReleased((int) mouseX, (int) mouseY, button); - } - - backgroundButton.mouseReleased((int) mouseX, (int) mouseY, button); - settingsButton.mouseReleased((int) mouseX, (int) mouseY, button); - return true; - } - - @Override - public boolean onCharTyped(char chr, int modifiers) { - if (showBackgroundWindow) { - exitBackgroundButton.charTyped(chr, modifiers); - addBackgroundButton.charTyped(chr, modifiers); - } - - if (showCustomizationWindow) { - darkModeSwitch.charTyped(chr, modifiers); - exitCustomizationButton.charTyped(chr, modifiers); - } - return true; - } - - @Override - public boolean onKeyPressed(int keyCode, int scanCode, int modifiers) { - if (showBackgroundWindow) { - exitBackgroundButton.keyPressed(keyCode, scanCode, modifiers); - addBackgroundButton.keyPressed(keyCode, scanCode, modifiers); - } - - if (showCustomizationWindow) { - darkModeSwitch.keyPressed(keyCode, scanCode, modifiers); - exitCustomizationButton.keyPressed(keyCode, scanCode, modifiers); - } - return super.onKeyPressed(keyCode, scanCode, modifiers); - } - - static class BackgroundItem { - String backgroundId; - File backgroundFile; - private final SimpleAnimation xAnimation = new SimpleAnimation(); - private final SimpleAnimation yAnimation = new SimpleAnimation(); - private final SimpleAnimation focusAnimation = new SimpleAnimation(); - boolean isDefault; - - public BackgroundItem(String backgroundId, File backgroundFile, boolean isDefault) { - this.backgroundId = backgroundId; - this.backgroundFile = backgroundFile; - this.isDefault = isDefault; - } - } - - private static class MainMenuButton { - private final PressAnimation pressAnimation = new PressAnimation(); - private final SimpleAnimation focusAnimation = new SimpleAnimation(); - private final String title; - private final String icon; - private final float x; - private final float y; - private final float width; - private final float height; - private final float scaleFactor; - private int[] pressedPos; - private final Runnable action; - - public MainMenuButton(String title, String icon, float x, float y, float width, float scaleFactor, Runnable action) { - this.title = title; - this.icon = icon; - this.x = x; - this.y = y; - this.width = width; - this.height = 50 * scaleFactor; - this.scaleFactor = scaleFactor; - this.action = action; - this.pressedPos = new int[]{0, 0}; - } - - private boolean enabled = true; - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public void draw(int mouseX, int mouseY) { - ColorPalette palette = PupperClient.getInstance().getColorManager().getPalette(); - boolean hovered = enabled && MouseUtils.isInside(mouseX, mouseY, x, y, width, height); - - focusAnimation.onTick(hovered ? 1.0F : 0, 12); - - float radius = 20 * scaleFactor; - - java.awt.Color bgColor = enabled ? palette.getSurface() : - ColorUtils.applyAlpha(palette.getSurface(), 0.5f); - java.awt.Color textColor = enabled ? - (hovered ? ColorUtils.blend(palette.getOnSurfaceVariant(), palette.getPrimary(), focusAnimation.getValue()) : - palette.getOnSurfaceVariant()) : - ColorUtils.applyAlpha(palette.getOnSurfaceVariant(), 0.5f); - - Skia.drawRoundedRect(x, y, width, height, radius, bgColor); - - if (enabled && hovered) { - java.awt.Color hoverColor = palette.getPrimary(); - Skia.drawRoundedRect(x, y, width, height, radius, - ColorUtils.applyAlpha(hoverColor, focusAnimation.getValue() * 0.12F)); - } - - if (enabled) { - Skia.save(); - Skia.clip(x, y, width, height, radius); - pressAnimation.draw(x + pressedPos[0], y + pressedPos[1], width, height, palette.getPrimary(), 1); - Skia.restore(); - } - - float fontSize = 18 * scaleFactor; - float iconSize = 22 * scaleFactor; - float iconPadding = 16 * scaleFactor; - - if (!title.isEmpty()) { - Skia.drawFullCenteredText(I18n.get(title), x + (width / 2), y + (height / 2), textColor, - Fonts.getRegular(fontSize)); - - Skia.drawHeightCenteredText(icon, x + iconPadding, y + (height / 2), textColor, Fonts.getIcon(iconSize)); - } else { - Skia.drawFullCenteredText(icon, x + (width / 2), y + (height / 2), textColor, Fonts.getIcon(iconSize)); - } - } - - public void mousePressed(int mouseX, int mouseY, int mouseButton) { - if (enabled && MouseUtils.isInside(mouseX, mouseY, x, y, width, height) && mouseButton == 0) { - pressedPos = new int[]{mouseX - (int) x, mouseY - (int) y}; - pressAnimation.onPressed(mouseX, mouseY, x, y); - } - } - - public void mouseReleased(int mouseX, int mouseY, int mouseButton) { - if (enabled && MouseUtils.isInside(mouseX, mouseY, x, y, width, height) && mouseButton == 0) { - action.run(); - } - pressAnimation.onReleased(mouseX, mouseY, x, y); - } - } -} diff --git a/src/main/java/cn/pupperclient/gui/MusicPlayGui.java b/src/main/java/cn/pupperclient/gui/MusicPlayGui.java index aafc59b..3c62fc1 100644 --- a/src/main/java/cn/pupperclient/gui/MusicPlayGui.java +++ b/src/main/java/cn/pupperclient/gui/MusicPlayGui.java @@ -1,31 +1,33 @@ package cn.pupperclient.gui; -import cn.pupperclient.gui.api.SimpleSoarGui; +import cn.pupperclient.event.EventListener; +import cn.pupperclient.event.skia.DrawSkiaEvent; +import cn.pupperclient.gui.api.PupperGuiUtil; import cn.pupperclient.skia.Skia; import cn.pupperclient.skia.font.Fonts; import cn.pupperclient.skia.font.Icon; +import cn.pupperclient.utils.minecraft.interfaces.IMinecraft; import cn.pupperclient.utils.mouse.MouseUtils; -import io.github.humbleui.types.Rect; +import net.minecraft.client.input.MouseButtonEvent; +import net.minecraft.network.chat.Component; +import org.jspecify.annotations.NonNull; import java.awt.*; -public class MusicPlayGui extends SimpleSoarGui { +public class MusicPlayGui extends PupperGuiUtil implements IMinecraft { private boolean isfullscreen = false; + private final int uiWidth = 1350; + private final int uiHeight = 900; + public MusicPlayGui() { - super(false); + super(Component.literal("MusicPlay")); } - @Override - public void draw(double mouseX, double mouseY) { - int windowWidth = client.getWindow().getWidth(); - int windowHeight = client.getWindow().getHeight(); - - float uiWidth = 1350; - float uiHeight = 900; - - float offsetX = (windowWidth - uiWidth) / 2; - float offsetY = (windowHeight - uiHeight) / 2; + @EventListener + public void draw(DrawSkiaEvent event) { + var offsetX = (windowWidth - uiWidth) / 2; + var offsetY = (windowHeight - uiHeight) / 2; Skia.translate(offsetX, offsetY); Skia.drawRect(0, 0, 340, uiHeight, new Color(20, 20, 20, 240)); @@ -34,6 +36,7 @@ public void draw(double mouseX, double mouseY) { Skia.drawText("Minecraft Jagget MusicPlay", 20, 26, Color.WHITE, Fonts.getRegular(23)); Skia.drawText(Icon.CLOSE, 1320, 20, Color.WHITE, Fonts.getIconFill(21)); + if (!isfullscreen) { Skia.drawText(Icon.FULLSCREEN, 1285, 19, Color.WHITE, Fonts.getIconFill(21)); } else { @@ -43,28 +46,27 @@ public void draw(double mouseX, double mouseY) { } @Override - public boolean onMousePressed(double mouseX, double mouseY, int button) { - int windowWidth = client.getWindow().getWidth(); - int windowHeight = client.getWindow().getHeight(); - - float uiWidth = 1350; - float uiHeight = 900; + public boolean mouseClicked(@NonNull MouseButtonEvent click, boolean doubled) { + var mouseX = click.x(); + var mouseY = click.y(); - float startX = (windowWidth - uiWidth) / 2; - float startY = (windowHeight - uiHeight) / 2; + var offsetX = (windowWidth - uiWidth) / 2; + var offsetY = (windowHeight - uiHeight) / 2; - Rect icon_CLOSE_rect = Skia.getTextBounds(Icon.CLOSE, Fonts.getIconFill(21)); - Rect icon_FULLSCREEN_rect = Skia.getTextBounds(Icon.FULLSCREEN, Fonts.getIconFill(21)); - Rect icon_FULLSCREEN_EXIT_rect = Skia.getTextBounds(Icon.FULLSCREEN_EXIT, Fonts.getIconFill(21)); - Rect icon_MINIMIZE_rect = Skia.getTextBounds(Icon.MINIMIZE, Fonts.getIconFill(21)); + var icon_CLOSE_rect = Skia.getTextBounds(Icon.CLOSE, Fonts.getIconFill(21)); + var icon_FULLSCREEN_rect = Skia.getTextBounds(Icon.FULLSCREEN, Fonts.getIconFill(21)); + var icon_MINIMIZE_rect = Skia.getTextBounds(Icon.MINIMIZE, Fonts.getIconFill(21)); - if (MouseUtils.isInside(mouseX, mouseY, startX + 1320, startY + 20, icon_CLOSE_rect.getWidth(), icon_CLOSE_rect.getHeight()) || - MouseUtils.isInside(mouseX, mouseY, startX + 1251, startY + 25, icon_MINIMIZE_rect.getWidth(), icon_MINIMIZE_rect.getHeight()) + if (MouseUtils.isInside(mouseX, mouseY, offsetX + 1320, offsetY + 20, icon_CLOSE_rect.getWidth(), icon_CLOSE_rect.getHeight()) || + MouseUtils.isInside(mouseX, mouseY, offsetX + 1251, offsetY + 25, icon_MINIMIZE_rect.getWidth(), icon_MINIMIZE_rect.getHeight()) ) { client.setScreen(null); - } else if (MouseUtils.isInside(mouseX, mouseY, startX + 1285, startY + 19, icon_FULLSCREEN_rect.getWidth() + 1, icon_FULLSCREEN_rect.getHeight() + 1)) { + return true; + } + if (MouseUtils.isInside(mouseX, mouseY, offsetX + 1285, offsetY + 19, icon_FULLSCREEN_rect.getWidth() + 1, icon_FULLSCREEN_rect.getHeight() + 1)) { isfullscreen = !isfullscreen; + return true; } - return true; + return false; } } diff --git a/src/main/java/cn/pupperclient/gui/api/PupperGuiUtil.java b/src/main/java/cn/pupperclient/gui/api/PupperGuiUtil.java new file mode 100644 index 0000000..65d1216 --- /dev/null +++ b/src/main/java/cn/pupperclient/gui/api/PupperGuiUtil.java @@ -0,0 +1,73 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.gui.api; + +import cn.pupperclient.event.EventBus; +import cn.pupperclient.utils.minecraft.interfaces.IMinecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import org.jspecify.annotations.NonNull; + +public abstract class PupperGuiUtil extends Screen implements IMinecraft { + public int windowWidth = 0; + public int windowHeight = 0; + + protected boolean isEventRegister; + + protected PupperGuiUtil(final Component title) { + super(title); + } + + protected void checkWindow() { + if (windowHeight == 0 || windowWidth == 0) { + this.windowWidth = client.getWindow().getWidth(); + this.windowHeight = client.getWindow().getHeight(); + } + } + + protected void initWindow() { + this.windowWidth = client.getWindow().getWidth(); + this.windowHeight = client.getWindow().getHeight(); + } + + protected void eventRegister() { + if (!isEventRegister) { + EventBus.getInstance().register(this); + isEventRegister = true; + } + } + + @Override + public void onClose() { + EventBus.getInstance().unregister(this); + isEventRegister = false; + super.onClose(); + } + + @Override + public void removed() { + EventBus.getInstance().unregister(this); + isEventRegister = false; + super.removed(); + } + + @Override + public void init() { + initWindow(); + eventRegister(); + } + + @Override + public boolean isPauseScreen() { + return false; + } + + @Override + public void extractRenderState(final @NonNull GuiGraphicsExtractor graphics, final int mouseX, final int mouseY, final float a) { + checkWindow(); + eventRegister(); + } +} diff --git a/src/main/java/cn/pupperclient/gui/api/SimpleSoarGui.java b/src/main/java/cn/pupperclient/gui/api/SimpleSoarGui.java index eb05431..0df07b6 100644 --- a/src/main/java/cn/pupperclient/gui/api/SimpleSoarGui.java +++ b/src/main/java/cn/pupperclient/gui/api/SimpleSoarGui.java @@ -1,12 +1,16 @@ package cn.pupperclient.gui.api; +import cn.pupperclient.event.EventBus; +import cn.pupperclient.event.EventListener; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.skia.Skia; -import cn.pupperclient.skia.context.SkiaContext; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.input.CharacterEvent; +import net.minecraft.client.input.KeyEvent; +import net.minecraft.client.input.MouseButtonEvent; +import net.minecraft.network.chat.Component; /** * Base class for all PupperClient GUIs. @@ -14,17 +18,21 @@ */ public abstract class SimpleSoarGui extends Screen { - protected final MinecraftClient client = MinecraftClient.getInstance(); + protected final Minecraft client = Minecraft.getInstance(); protected final boolean mcScale; + private boolean registered; protected SimpleSoarGui(boolean mcScale) { - super(Text.empty()); - this.mcScale = mcScale; + super(Component.empty()); + this.mcScale = true; } @Override protected void init() { - // Base init logic if any + if (client.level != null && !registered) { + EventBus.getInstance().register(this); + registered = true; + } } /** @@ -33,65 +41,73 @@ protected void init() { public abstract void draw(double mouseX, double mouseY); @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - SkiaContext.draw((skiaContext) -> { - Skia.save(); - - if (mcScale) { - Skia.scale((float) client.getWindow().getScaleFactor()); - } - - // Standardize mouse coordinates based on scaling - double finalMouseX = mcScale ? mouseX : client.mouse.getX(); - double finalMouseY = mcScale ? mouseY : client.mouse.getY(); - - draw(finalMouseX, finalMouseY); - - Skia.restore(); - }); + public void extractRenderState(GuiGraphicsExtractor context, int mouseX, int mouseY, float delta) { + if (client.level != null && !registered) { + EventBus.getInstance().register(this); + registered = true; + } } @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - double finalMouseX = mcScale ? mouseX : client.mouse.getX(); - double finalMouseY = mcScale ? mouseY : client.mouse.getY(); - return onMousePressed(finalMouseX, finalMouseY, button); + public boolean mouseClicked(MouseButtonEvent click, boolean doubled) { + double guiScale = client.getWindow().getGuiScale(); + return onMousePressed(client.mouseHandler.xpos() / guiScale, client.mouseHandler.ypos() / guiScale, click.button(), doubled); } @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - double finalMouseX = mcScale ? mouseX : client.mouse.getX(); - double finalMouseY = mcScale ? mouseY : client.mouse.getY(); - return onMouseReleased(finalMouseX, finalMouseY, button); + public boolean mouseReleased(MouseButtonEvent click) { + double guiScale = client.getWindow().getGuiScale(); + return onMouseReleased(client.mouseHandler.xpos() / guiScale, client.mouseHandler.ypos() / guiScale, click.button()); } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { - double finalMouseX = mcScale ? mouseX : client.mouse.getX(); - double finalMouseY = mcScale ? mouseY : client.mouse.getY(); - return onMouseScrolled(finalMouseX, finalMouseY, horizontalAmount, verticalAmount); + double guiScale = client.getWindow().getGuiScale(); + return onMouseScrolled(client.mouseHandler.xpos() / guiScale, client.mouseHandler.ypos() / guiScale, horizontalAmount, verticalAmount); } @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - return onKeyPressed(keyCode, scanCode, modifiers); + public boolean keyPressed(KeyEvent event) { + return onKeyPressed(event.key(), event.scancode(), event.modifiers()); } @Override - public boolean charTyped(char chr, int modifiers) { - return onCharTyped(chr, modifiers); + public boolean charTyped(CharacterEvent input) { + return onCharTyped(input.codepoint()); } // Abstract or hook methods for subclasses to implement without overriding Screen methods directly - public boolean onMousePressed(double mouseX, double mouseY, int button) { return false; } + public boolean onMousePressed(double mouseX, double mouseY, int button, boolean doubled) { return false; } public boolean onMouseReleased(double mouseX, double mouseY, int button) { return false; } public boolean onMouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { return false; } - public boolean onKeyPressed(int keyCode, int scanCode, int modifiers) { return super.keyPressed(keyCode, scanCode, modifiers); } - public boolean onCharTyped(char chr, int modifiers) { return super.charTyped(chr, modifiers); } + public boolean onKeyPressed(int keyCode, int scanCode, int modifiers) { return super.keyPressed(new KeyEvent(keyCode, scanCode, modifiers)); } + public boolean onCharTyped(int chr) { return super.charTyped(new CharacterEvent(chr)); } @Override - public boolean shouldPause() { + public void removed() { + if (registered) { + EventBus.getInstance().unregister(this); + registered = false; + } + super.removed(); + } + + @Override + public boolean isPauseScreen() { return false; } + + @EventListener + public void onRenderSkia(RenderSkiaEvent event) { + if (client.level == null) { + return; + } + if (client.screen == this) { + double guiScale = client.getWindow().getGuiScale(); + Skia.save(); + draw(client.mouseHandler.xpos() / guiScale, client.mouseHandler.ypos() / guiScale); + Skia.restore(); + } + } } diff --git a/src/main/java/cn/pupperclient/gui/api/SoarGui.java b/src/main/java/cn/pupperclient/gui/api/SoarGui.java index 6127782..9ac6b6d 100644 --- a/src/main/java/cn/pupperclient/gui/api/SoarGui.java +++ b/src/main/java/cn/pupperclient/gui/api/SoarGui.java @@ -4,7 +4,6 @@ import java.util.List; import cn.pupperclient.PupperClient; -import cn.pupperclient.shader.impl.Kawaseblur; import org.lwjgl.glfw.GLFW; import cn.pupperclient.animation.Animation; @@ -14,12 +13,10 @@ import cn.pupperclient.gui.api.page.SimplePage; import cn.pupperclient.management.color.api.ColorPalette; import cn.pupperclient.management.config.ConfigType; -import cn.pupperclient.management.mod.impl.settings.ModMenuSettings; import cn.pupperclient.skia.Skia; import cn.pupperclient.ui.component.Component; -import io.github.humbleui.skija.SurfaceOrigin; -import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screens.Screen; public abstract class SoarGui extends SimpleSoarGui { @@ -63,11 +60,6 @@ public void draw(double mouseX, double mouseY) { ColorPalette palette = PupperClient.getInstance().getColorManager().getPalette(); - if (ModMenuSettings.getInstance().getBlurSetting().isEnabled()) { - Skia.drawImage(Kawaseblur.GUI_BLUR.getTexture(), 0, 0, client.getWindow().getWidth(), - client.getWindow().getHeight(), inOutAnimation.getValue(), SurfaceOrigin.BOTTOM_LEFT); - } - Skia.save(); Skia.setAlpha((int) (inOutAnimation.getValue() * 255)); Skia.scale(getX(), getY(), getWidth(), getHeight(), 2 - inOutAnimation.getValue()); @@ -125,7 +117,7 @@ public void draw(double mouseX, double mouseY) { } @Override - public boolean onMousePressed(double mouseX, double mouseY, int button) { + public boolean onMousePressed(double mouseX, double mouseY, int button, boolean doubled) { if (currentPage != null) { currentPage.mousePressed(mouseX, mouseY, button); @@ -159,14 +151,14 @@ public boolean onMouseScrolled(double mouseX, double mouseY, double horizontalAm } @Override - public boolean onCharTyped(char chr, int modifiers) { + public boolean onCharTyped(int chr) { if (currentPage != null) { - currentPage.charTyped(chr, modifiers); + currentPage.charTyped(chr); } for (Component c : components) { - c.charTyped(chr, modifiers); + c.charTyped(chr); } return true; } diff --git a/src/main/java/cn/pupperclient/gui/api/page/Page.java b/src/main/java/cn/pupperclient/gui/api/page/Page.java index 19512cc..88effa3 100644 --- a/src/main/java/cn/pupperclient/gui/api/page/Page.java +++ b/src/main/java/cn/pupperclient/gui/api/page/Page.java @@ -55,8 +55,8 @@ public void mouseReleased(double mouseX, double mouseY, int button) { } @Override - public void charTyped(char chr, int modifiers) { - searchBar.charTyped(chr, modifiers); + public void charTyped(int chr) { + searchBar.charTyped(chr); } @Override diff --git a/src/main/java/cn/pupperclient/gui/api/page/SimplePage.java b/src/main/java/cn/pupperclient/gui/api/page/SimplePage.java index 5b082a3..30535dd 100644 --- a/src/main/java/cn/pupperclient/gui/api/page/SimplePage.java +++ b/src/main/java/cn/pupperclient/gui/api/page/SimplePage.java @@ -39,7 +39,7 @@ public void mouseReleased(double mouseX, double mouseY, int button) { public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { } - public void charTyped(char chr, int modifiers) { + public void charTyped(int chr) { } public void keyPressed(int keyCode, int scanCode, int modifiers) { diff --git a/src/main/java/cn/pupperclient/gui/edithud/GuiEditHUD.java b/src/main/java/cn/pupperclient/gui/edithud/GuiEditHUD.java index 264d461..63aa610 100644 --- a/src/main/java/cn/pupperclient/gui/edithud/GuiEditHUD.java +++ b/src/main/java/cn/pupperclient/gui/edithud/GuiEditHUD.java @@ -4,7 +4,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; - +import net.minecraft.client.gui.screens.Screen; import cn.pupperclient.PupperClient; import org.lwjgl.glfw.GLFW; @@ -17,7 +17,6 @@ import it.unimi.dsi.fastutil.floats.FloatArrayList; import it.unimi.dsi.fastutil.objects.ObjectObjectImmutablePair; -import net.minecraft.client.gui.screen.Screen; public class GuiEditHUD extends SimpleSoarGui { @@ -81,7 +80,7 @@ private float calculateNewScale(float currentScale, double wheelDelta) { } @Override - public boolean onMousePressed(double mouseX, double mouseY, int button) { + public boolean onMousePressed(double mouseX, double mouseY, int button, boolean doubled) { getHoveredMod(mouseX, mouseY).ifPresent(mod -> { if (button == GLFW.GLFW_MOUSE_BUTTON_MIDDLE) { mod.getPosition().setScale(1.0F); @@ -195,7 +194,7 @@ private FloatArrayList getSnappingLines(boolean isHorizontal) { FloatArrayList lines = new FloatArrayList(); - lines.add(isHorizontal ? client.getWindow().getScaledWidth() / 2F : client.getWindow().getScaledHeight() / 2F); + lines.add(isHorizontal ? client.getWindow().getGuiScaledWidth() / 2F : client.getWindow().getGuiScaledHeight() / 2F); mods.stream().filter( mod -> isModInteractable(mod) && !selectedMod.map(pair -> pair.left().equals(mod)).orElse(false)) diff --git a/src/main/java/cn/pupperclient/gui/edithud/api/SnappingLine.java b/src/main/java/cn/pupperclient/gui/edithud/api/SnappingLine.java index b175c8f..2a8ec7d 100644 --- a/src/main/java/cn/pupperclient/gui/edithud/api/SnappingLine.java +++ b/src/main/java/cn/pupperclient/gui/edithud/api/SnappingLine.java @@ -1,11 +1,9 @@ package cn.pupperclient.gui.edithud.api; import java.awt.Color; - +import net.minecraft.client.Minecraft; import cn.pupperclient.skia.Skia; -import net.minecraft.client.MinecraftClient; - public class SnappingLine { private float line; @@ -35,15 +33,15 @@ public SnappingLine(float line, float left, float size, boolean multipleSides) { public void drawLine(float lineWidth, boolean isX) { - MinecraftClient client = MinecraftClient.getInstance(); + Minecraft client = Minecraft.getInstance(); Color color = Color.WHITE; float pos = (float) (line - lineWidth / 2f); if (isX) { - Skia.drawLine(pos, 0, pos, client.getWindow().getScaledHeight(), lineWidth, color); + Skia.drawLine(pos, 0, pos, client.getWindow().getGuiScaledHeight(), lineWidth, color); } else { - Skia.drawLine(0, pos, client.getWindow().getScaledWidth(), pos, lineWidth, color); + Skia.drawLine(0, pos, client.getWindow().getGuiScaledWidth(), pos, lineWidth, color); } } diff --git a/src/main/java/cn/pupperclient/gui/modmenu/GuiModMenu.java b/src/main/java/cn/pupperclient/gui/modmenu/GuiModMenu.java index 8695252..b4b9629 100644 --- a/src/main/java/cn/pupperclient/gui/modmenu/GuiModMenu.java +++ b/src/main/java/cn/pupperclient/gui/modmenu/GuiModMenu.java @@ -13,7 +13,7 @@ public class GuiModMenu extends SoarGui { private NavigationRail navigationRail; public GuiModMenu() { - super(false); + super(true); } @Override @@ -49,12 +49,12 @@ public List createPages() { @Override public float getX() { - return ((float) client.getWindow().getWidth() / 2) - (getWidth() / 2); + return ((float) client.getWindow().getGuiScaledWidth() / 2) - (getWidth() / 2); } @Override public float getY() { - return ((float) client.getWindow().getHeight() / 2) - (getHeight() / 2); + return ((float) client.getWindow().getGuiScaledHeight() / 2) - (getHeight() / 2); } @Override diff --git a/src/main/java/cn/pupperclient/gui/modmenu/component/MusicControlBar.java b/src/main/java/cn/pupperclient/gui/modmenu/component/MusicControlBar.java index b00a12d..802c84b 100644 --- a/src/main/java/cn/pupperclient/gui/modmenu/component/MusicControlBar.java +++ b/src/main/java/cn/pupperclient/gui/modmenu/component/MusicControlBar.java @@ -233,10 +233,10 @@ public void keyPressed(int keyCode, int scanCode, int modifiers) { } @Override - public void charTyped(char chr, int modifiers) { + public void charTyped(int chr) { if (addMusic) { for (Component c : components) { - c.charTyped(chr, modifiers); + c.charTyped(chr); } } } diff --git a/src/main/java/cn/pupperclient/gui/modmenu/component/SettingBar.java b/src/main/java/cn/pupperclient/gui/modmenu/component/SettingBar.java index 3d78956..db38172 100644 --- a/src/main/java/cn/pupperclient/gui/modmenu/component/SettingBar.java +++ b/src/main/java/cn/pupperclient/gui/modmenu/component/SettingBar.java @@ -35,8 +35,7 @@ import cn.pupperclient.ui.component.impl.Switch; import cn.pupperclient.ui.component.impl.text.TextField; import cn.pupperclient.utils.language.I18n; - -import net.minecraft.client.util.InputUtil; +import com.mojang.blaze3d.platform.InputConstants; public class SettingBar extends Component { @@ -93,7 +92,7 @@ public void onChanged(String option) { Keybind bind = new Keybind(0, 0, kSetting.getKey()); bind.setHandler(new KeybindHandler() { @Override - public void onBinded(InputUtil.Key key) { + public void onBinded(InputConstants.Key key) { kSetting.setKey(key); } }); @@ -202,10 +201,10 @@ public void mouseReleased(double mouseX, double mouseY, int button) { } @Override - public void charTyped(char chr, int modifiers) { + public void charTyped(int chr) { if (component != null) { - component.charTyped(chr, modifiers); + component.charTyped(chr); } } diff --git a/src/main/java/cn/pupperclient/gui/modmenu/pages/CosmeticsPage.java b/src/main/java/cn/pupperclient/gui/modmenu/pages/CosmeticsPage.java index 1a6c11e..a49c718 100644 --- a/src/main/java/cn/pupperclient/gui/modmenu/pages/CosmeticsPage.java +++ b/src/main/java/cn/pupperclient/gui/modmenu/pages/CosmeticsPage.java @@ -20,12 +20,12 @@ import cn.pupperclient.utils.file.FileDialog; import cn.pupperclient.utils.language.I18n; import cn.pupperclient.utils.mouse.MouseUtils; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.Identifier; +import net.minecraft.resources.Identifier; import org.lwjgl.glfw.GLFW; import io.github.humbleui.skija.Font; import javax.imageio.ImageIO; +import net.minecraft.client.Minecraft; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -114,7 +114,7 @@ private void uploadCape() { try { Files.copy(selectedFile.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - MinecraftClient.getInstance().execute(this::loadExistingCapes); + Minecraft.getInstance().execute(this::loadExistingCapes); } catch (IOException e) { cn.pupperclient.PupperLogger.error("CosmeticsPage", "Failed to copy uploaded cape", e); } diff --git a/src/main/java/cn/pupperclient/gui/modmenu/pages/MusicPage.java b/src/main/java/cn/pupperclient/gui/modmenu/pages/MusicPage.java index 6eea4e3..1f71c22 100644 --- a/src/main/java/cn/pupperclient/gui/modmenu/pages/MusicPage.java +++ b/src/main/java/cn/pupperclient/gui/modmenu/pages/MusicPage.java @@ -294,9 +294,9 @@ public void keyPressed(int keyCode, int scanCode, int modifiers) { } @Override - public void charTyped(char chr, int modifiers) { - super.charTyped(chr, modifiers); - controlBar.charTyped(chr, modifiers); + public void charTyped(int chr) { + super.charTyped(chr); + controlBar.charTyped(chr); } private void drawRoundedImage(File file, float x, float y, float width, float height, float cornerRadius, diff --git a/src/main/java/cn/pupperclient/gui/modmenu/pages/SettingsImplPage.java b/src/main/java/cn/pupperclient/gui/modmenu/pages/SettingsImplPage.java index 4dfb9a9..e1249d9 100644 --- a/src/main/java/cn/pupperclient/gui/modmenu/pages/SettingsImplPage.java +++ b/src/main/java/cn/pupperclient/gui/modmenu/pages/SettingsImplPage.java @@ -139,8 +139,8 @@ public void mouseReleased(double mouseX, double mouseY, int button) { } @Override - public void charTyped(char chr, int modifiers) { - super.charTyped(chr, modifiers); + public void charTyped(int chr) { + super.charTyped(chr); for (SettingBar b : bars) { @@ -148,7 +148,7 @@ public void charTyped(char chr, int modifiers) { continue; } - b.charTyped(chr, modifiers); + b.charTyped(chr); } } diff --git a/src/main/java/cn/pupperclient/gui/modmenu/pages/profile/ProfileAddPage.java b/src/main/java/cn/pupperclient/gui/modmenu/pages/profile/ProfileAddPage.java index 602e1c5..18bc93b 100644 --- a/src/main/java/cn/pupperclient/gui/modmenu/pages/profile/ProfileAddPage.java +++ b/src/main/java/cn/pupperclient/gui/modmenu/pages/profile/ProfileAddPage.java @@ -3,7 +3,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; - +import net.minecraft.client.Minecraft; import cn.pupperclient.PupperClient; import org.lwjgl.glfw.GLFW; @@ -27,7 +27,6 @@ import cn.pupperclient.utils.mouse.MouseUtils; import it.unimi.dsi.fastutil.objects.ObjectObjectImmutablePair; -import net.minecraft.client.MinecraftClient; public class ProfileAddPage extends SimplePage { @@ -46,7 +45,7 @@ public ProfileAddPage(SoarGui parent, Class prevPage) { @Override public void init() { - MinecraftClient client = MinecraftClient.getInstance(); + Minecraft client = Minecraft.getInstance(); components.clear(); super.init(); @@ -63,7 +62,7 @@ public void init() { @Override public void onAction() { if (!nameField.getText().isEmpty()) { - PupperClient.getInstance().getProfileManager().save(nameField.getText(), client.getGameProfile().getName(), + PupperClient.getInstance().getProfileManager().save(nameField.getText(), client.getGameProfile().name(), addressField.getText(), currentIcon, ConfigType.MOD); PupperClient.getInstance().getProfileManager().readProfiles(); parent.setClosable(true); @@ -177,11 +176,11 @@ public void mouseReleased(double mouseX, double mouseY, int button) { } @Override - public void charTyped(char chr, int modifiers) { - super.charTyped(chr, modifiers); + public void charTyped(int chr) { + super.charTyped(chr); for (Component component : components) { - component.charTyped(chr, modifiers); + component.charTyped(chr); } } diff --git a/src/main/java/cn/pupperclient/gui/welcomegui/TermsScreen.java b/src/main/java/cn/pupperclient/gui/welcomegui/TermsScreen.java deleted file mode 100644 index 2d3440a..0000000 --- a/src/main/java/cn/pupperclient/gui/welcomegui/TermsScreen.java +++ /dev/null @@ -1,119 +0,0 @@ -package cn.pupperclient.gui.welcomegui; - -import cn.pupperclient.PupperClient; -import cn.pupperclient.gui.api.SimpleSoarGui; -import cn.pupperclient.skia.Skia; -import cn.pupperclient.skia.font.Fonts; -import cn.pupperclient.ui.component.handler.impl.ButtonHandler; -import cn.pupperclient.ui.component.impl.Button; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.sound.SoundEvents; - -import java.awt.Color; - -public class TermsScreen extends SimpleSoarGui { - private int centerX; - private int centerY; - private boolean accepted = false; - - private Button acceptButton; - private Button declineButton; - - public TermsScreen() { - super(false); - } - - @Override - public void init() { - acceptButton = new Button("text.accept", 0, 0, Button.Style.TONAL); - acceptButton.setHandler(new ButtonHandler() { - @Override - public void onAction() { - accepted = true; - if (client.player != null) { - client.player.playSound(SoundEvents.UI_TOAST_IN, 1.0f, 1.0f); - } - PupperClient.hasAcceptedTerms = true; - client.setScreen(null); - } - }); - - declineButton = new Button("text.decline", 0, 0, Button.Style.TONAL); - declineButton.setHandler(new ButtonHandler() { - @Override - public void onAction() { - client.setScreen(new TitleScreen()); - } - }); - - rebuildLayout(); - } - - @Override - public void resize(MinecraftClient client, int width, int height) { - super.resize(client, width, height); - rebuildLayout(); - } - - private void updatePositions() { - centerX = client.getWindow().getWidth() / 2; - centerY = client.getWindow().getHeight() / 2; - } - - private void rebuildLayout() { - updatePositions(); - - float acceptWidth = acceptButton.getWidth(); - float declineWidth = declineButton.getWidth(); - - float totalWidth = acceptWidth + declineWidth + 10; - float startX = centerX - totalWidth / 2; - - acceptButton.setX(startX); - acceptButton.setY(centerY + 20); - - declineButton.setX(startX + acceptWidth + 10); - declineButton.setY(centerY + 20); - } - - @Override - public void draw(double mouseX, double mouseY) { - drawTranslucentBackground(); - - renderSkijaWelcome(mouseX, mouseY); - } - - private void drawTranslucentBackground() { - Color translucentBlack = new Color(0, 0, 0, 180); - Skia.drawRect(0, 0, client.getWindow().getWidth(), client.getWindow().getHeight(), translucentBlack); - } - - private void renderSkijaWelcome(double mouseX, double mouseY) { - Skia.drawFullCenteredText("Terms of Service", centerX, centerY - 60, Color.WHITE, Fonts.getRegular(20)); - - Skia.drawFullCenteredText("Please read and accept the Terms of Service", - centerX, centerY - 20, Color.WHITE, Fonts.getRegular(14)); - - acceptButton.draw(mouseX, mouseY); - declineButton.draw(mouseX, mouseY); - } - - @Override - public boolean onMousePressed(double mouseX, double mouseY, int button) { - acceptButton.mousePressed(mouseX, mouseY, button); - declineButton.mousePressed(mouseX, mouseY, button); - return true; - } - - @Override - public boolean onMouseReleased(double mouseX, double mouseY, int button) { - acceptButton.mouseReleased(mouseX, mouseY, button); - declineButton.mouseReleased(mouseX, mouseY, button); - return true; - } - - public boolean isAccepted() { - return accepted; - } -} diff --git a/src/main/java/cn/pupperclient/management/cape/CapeManager.java b/src/main/java/cn/pupperclient/management/cape/CapeManager.java index 17b6c9b..4d73ec3 100644 --- a/src/main/java/cn/pupperclient/management/cape/CapeManager.java +++ b/src/main/java/cn/pupperclient/management/cape/CapeManager.java @@ -1,22 +1,23 @@ package cn.pupperclient.management.cape; +import cn.pupperclient.PupperClient; +import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.texture.NativeImage; -import net.minecraft.client.texture.NativeImageBackedTexture; -import net.minecraft.util.Identifier; - import java.io.Closeable; import java.io.IOException; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.core.ClientAsset; +import net.minecraft.resources.Identifier; public class CapeManager implements Closeable { private static CapeManager instance; private final Map loadedCapes = Collections.synchronizedMap(new HashMap<>()); - private final Map loadedCapeTextures = Collections.synchronizedMap(new HashMap<>()); + private final Map loadedCapeTextures = Collections.synchronizedMap(new HashMap<>()); private String selectedCapeId = null; @@ -39,9 +40,10 @@ public String getSelectedCapeId() { return selectedCapeId; } - public Identifier getSelectedCapeTexture() { + public ClientAsset.Texture getSelectedCapeTexture() { if (selectedCapeId == null) return null; - return getLoadedCape(selectedCapeId); + var capeTexture = getLoadedCape(selectedCapeId); + return new ClientAsset.ResourceTexture(Identifier.fromNamespaceAndPath(PupperClient.getModId(), "capes/selectedcape"), capeTexture); } public void clearSelectedCape() { @@ -52,11 +54,11 @@ public void loadCape(String id, byte[] textureData) { if (id == null || textureData == null) return; executorService.submit(() -> { - RenderSystem.recordRenderCall(() -> { - NativeImageBackedTexture nativeImage = createNativeTexture(textureData); + RenderSystem.queueFencedTask(() -> { + DynamicTexture nativeImage = createNativeTexture(textureData); if (nativeImage != null) { - Identifier identifier = Identifier.of("pupper", namespace + "/" + id); - MinecraftClient.getInstance().getTextureManager().registerTexture(identifier, nativeImage); + Identifier identifier = Identifier.fromNamespaceAndPath("pupper", namespace + "/" + id); + Minecraft.getInstance().getTextureManager().register(identifier, nativeImage); loadedCapes.put(id, identifier); loadedCapeTextures.put(identifier, nativeImage); } @@ -73,11 +75,11 @@ public void unloadCape(String id) { Identifier cape = loadedCapes.remove(id); if (cape != null) { - NativeImageBackedTexture texture = loadedCapeTextures.remove(cape); + DynamicTexture texture = loadedCapeTextures.remove(cape); if (texture != null) { texture.close(); } - MinecraftClient.getInstance().getTextureManager().destroyTexture(cape); + Minecraft.getInstance().getTextureManager().release(cape); } } @@ -89,10 +91,10 @@ public Set getLoadedCapeIds() { return new HashSet<>(loadedCapes.keySet()); } - private static NativeImageBackedTexture createNativeTexture(byte[] bytes) { + private static DynamicTexture createNativeTexture(byte[] bytes) { if (bytes == null) return null; try { - return new NativeImageBackedTexture(NativeImage.read(bytes)); + return new DynamicTexture(() -> "pupper_capetexture", NativeImage.read(bytes)); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/cn/pupperclient/management/cape/CapeRenderer.java b/src/main/java/cn/pupperclient/management/cape/CapeRenderer.java index 1fc227d..9febcd4 100644 --- a/src/main/java/cn/pupperclient/management/cape/CapeRenderer.java +++ b/src/main/java/cn/pupperclient/management/cape/CapeRenderer.java @@ -1,49 +1,56 @@ package cn.pupperclient.management.cape; +import cn.pupperclient.PupperLogger; import cn.pupperclient.skia.Skia; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.Identifier; +import com.mojang.blaze3d.opengl.GlTexture; import io.github.humbleui.skija.ClipMode; import io.github.humbleui.skija.Path; import io.github.humbleui.skija.SurfaceOrigin; import io.github.humbleui.types.RRect; import io.github.humbleui.types.Rect; +import net.minecraft.client.Minecraft; +import net.minecraft.resources.Identifier; public class CapeRenderer { - public static void renderCapePreview(Identifier capeTexture, float x, float y, float width, float height) { + @SuppressWarnings("unused") + public static void renderCapePreview(Identifier capeTexture, float x, float y) { if (capeTexture == null) return; try { - int textureId = MinecraftClient.getInstance().getTextureManager().getTexture(capeTexture).getGlId(); + var texture = Minecraft.getInstance().getTextureManager().getTexture(capeTexture).getTexture(); - // 尝试不同的纹理尺寸 - boolean loaded = Skia.getImageHelper().load(textureId, 64, 32, SurfaceOrigin.TOP_LEFT) || - Skia.getImageHelper().load(textureId, 128, 64, SurfaceOrigin.TOP_LEFT); + if (texture instanceof GlTexture glTexture) { + int textureId = glTexture.glId(); + boolean loaded = Skia.getImageHelper().load(textureId, 64, 32, SurfaceOrigin.TOP_LEFT) || + Skia.getImageHelper().load(textureId, 128, 64, SurfaceOrigin.TOP_LEFT); - if (loaded) { - Skia.save(); - Skia.translate(x + 2, y + 8); - Skia.scale(2f, 2f, 1f); + if (loaded) { + Skia.save(); + Skia.translate(x + 2, y + 8); + Skia.scale(2f, 2f, 1f); - Rect srcRect = Rect.makeXYWH(1, 1, 10, 16); - Rect dstRect = Rect.makeXYWH(0, 0, 10, 16); - Skia.getCanvas().drawImageRect(Skia.getImageHelper().get(textureId), srcRect, dstRect, null, false); + Rect srcRect = Rect.makeXYWH(1, 1, 10, 16); + Rect dstRect = Rect.makeXYWH(0, 0, 10, 16); + Skia.getCanvas().drawImageRect(Skia.getImageHelper().get(textureId), srcRect, dstRect, null, false); - Skia.restore(); + Skia.restore(); - Skia.save(); - Skia.translate(x + 26, y + 8); - Skia.scale(2f, 2f, 1f); + Skia.save(); + Skia.translate(x + 26, y + 8); + Skia.scale(2f, 2f, 1f); - Rect srcRect2 = Rect.makeXYWH(12, 1, 10, 16); - Rect dstRect2 = Rect.makeXYWH(0, 0, 10, 16); - Skia.getCanvas().drawImageRect(Skia.getImageHelper().get(textureId), srcRect2, dstRect2, null, false); + Rect srcRect2 = Rect.makeXYWH(12, 1, 10, 16); + Rect dstRect2 = Rect.makeXYWH(0, 0, 10, 16); + Skia.getCanvas().drawImageRect(Skia.getImageHelper().get(textureId), srcRect2, dstRect2, null, false); - Skia.restore(); + Skia.restore(); + } + } else { + PupperLogger.warn("CapeRenderer", "Failed to render cape preview: : unknown glTexture"); } } catch (Exception e) { - System.err.println("Failed to render cape preview: " + e.getMessage()); + PupperLogger.warn("CapeRenderer", "Failed to render cape preview: " + e.getMessage()); } } @@ -52,26 +59,28 @@ public static void renderRoundedCapePreview(Identifier capeTexture, float x, flo if (capeTexture == null) return; try { - int textureId = MinecraftClient.getInstance().getTextureManager().getTexture(capeTexture).getGlId(); - - // 尝试不同的纹理尺寸 - boolean loaded = Skia.getImageHelper().load(textureId, 64, 32, SurfaceOrigin.TOP_LEFT) || - Skia.getImageHelper().load(textureId, 128, 64, SurfaceOrigin.TOP_LEFT); - - if (loaded) { - Path path = Path.makeRRect(RRect.makeXYWH(x, y, width, height, radius)); - - // 根据实际纹理尺寸调整源矩形 - Rect srcRect = Rect.makeXYWH(1, 1, 10, 16); - Rect dstRect = Rect.makeXYWH(x, y, width, height); - - Skia.save(); - Skia.getCanvas().clipPath(path, ClipMode.INTERSECT, true); - Skia.getCanvas().drawImageRect(Skia.getImageHelper().get(textureId), srcRect, dstRect, null, false); - Skia.restore(); + var texture = Minecraft.getInstance().getTextureManager().getTexture(capeTexture).getTexture(); + if (texture instanceof GlTexture glTexture) { + int textureId = glTexture.glId(); + boolean loaded = Skia.getImageHelper().load(textureId, 64, 32, SurfaceOrigin.TOP_LEFT) || + Skia.getImageHelper().load(textureId, 128, 64, SurfaceOrigin.TOP_LEFT); + + if (loaded) { + Path path = Path.makeRRect(RRect.makeXYWH(x, y, width, height, radius)); + + Rect srcRect = Rect.makeXYWH(1, 1, 10, 16); + Rect dstRect = Rect.makeXYWH(x, y, width, height); + + Skia.save(); + Skia.getCanvas().clipPath(path, ClipMode.INTERSECT, true); + Skia.getCanvas().drawImageRect(Skia.getImageHelper().get(textureId), srcRect, dstRect, null, false); + Skia.restore(); + } + } else { + PupperLogger.warn("CapeRenderer", "Failed to render rounded cape preview: unknown glTexture"); } } catch (Exception e) { - System.err.println("Failed to render rounded cape preview: " + e.getMessage()); + PupperLogger.warn("CapeRenderer", "Failed to render rounded cape preview: " + e.getMessage()); } } } diff --git a/src/main/java/cn/pupperclient/management/command/PupperCommand.java b/src/main/java/cn/pupperclient/management/command/PupperCommand.java index 18a33a7..68e1e32 100644 --- a/src/main/java/cn/pupperclient/management/command/PupperCommand.java +++ b/src/main/java/cn/pupperclient/management/command/PupperCommand.java @@ -1,6 +1,7 @@ package cn.pupperclient.management.command; import cn.pupperclient.PupperClient; +import cn.pupperclient.PupperLogger; import cn.pupperclient.management.command.impl.*; import cn.pupperclient.management.mod.Mod; import cn.pupperclient.management.mod.ModManager; @@ -8,13 +9,13 @@ import cn.pupperclient.utils.minecraft.interfaces.IMinecraft; import cn.pupperclient.utils.language.I18n; import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; - +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; import java.io.IOException; +import java.util.Objects; public class PupperCommand implements IMinecraft { private static final String PREFIX = "."; @@ -40,7 +41,6 @@ public static void runCommand(String command) throws IOException { if (args.length == 0) { showHelp(); - return; } String mainCommand = args[0].toLowerCase(); @@ -123,16 +123,16 @@ private static void showHelp() { private static void listMods() { if (modManager == null) { - ChatUtils.addChatMessage(Text.literal("§c" + I18n.get("modManager.notInitialized"))); + ChatUtils.addChatMessage(Component.literal("§c" + I18n.get("modManager.notInitialized"))); return; } // 创建标题和刷新按钮 - MutableText title = Text.literal("=== " + I18n.get("command.help.modlist.title") + " ===") - .formatted(Formatting.GOLD); + MutableComponent title = Component.literal("=== " + I18n.get("command.help.modlist.title") + " ===") + .withStyle(ChatFormatting.GOLD); - MutableText refreshButton = createClickableText(" [" + I18n.get("command.help.modlist.refresh") + "]", ".list", - I18n.get("command.help.modlist.refresh.tip"), Formatting.GREEN); + MutableComponent refreshButton = createClickableText(" [" + I18n.get("command.help.modlist.refresh") + "]", ".list", + I18n.get("command.help.modlist.refresh.tip"), ChatFormatting.GREEN); title.append(refreshButton); ChatUtils.addChatMessage(title); @@ -150,44 +150,46 @@ private static void listMods() { boolean isEnabled = mod.isEnabled(); String shortModName = getShortModName(mod.getName()); - MutableText modNameText = Text.literal("• " + modDisplayName) - .formatted(Formatting.AQUA); + MutableComponent modNameText = Component.literal("• " + modDisplayName) + .withStyle(ChatFormatting.AQUA); - MutableText statusText; + MutableComponent statusText; if (isEnabled) { statusText = createClickableText(I18n.get("mod.enabled"), ".toggle " + shortModName, - I18n.get("modNameText.c") + " " + modDisplayName, Formatting.GREEN); + I18n.get("modNameText.c") + " " + modDisplayName, ChatFormatting.GREEN); } else { statusText = createClickableText(I18n.get("mod.disabled"), ".toggle " + shortModName, - I18n.get("modNameText.d") + " " + modDisplayName, Formatting.RED); + I18n.get("modNameText.d") + " " + modDisplayName, ChatFormatting.RED); } - MutableText modLine = Text.empty() + MutableComponent modLine = Component.empty() .append(modNameText) - .append(Text.literal(" - ").formatted(Formatting.GRAY)) + .append(Component.literal(" - ").withStyle(ChatFormatting.GRAY)) .append(statusText); ChatUtils.addChatMessage(modLine); } // 统计信息行 - MutableText stats = Text.literal(I18n.get("command.help.modlist.stats") + ": ") - .formatted(Formatting.GRAY) - .append(Text.literal(enabledCount + "/" + totalCount + " " + I18n.get("mod.enabled")) - .formatted(enabledCount > 0 ? Formatting.GREEN : Formatting.RED)); + MutableComponent stats = Component.literal(I18n.get("command.help.modlist.stats") + ": ") + .withStyle(ChatFormatting.GRAY) + .append(Component.literal(enabledCount + "/" + totalCount + " " + I18n.get("mod.enabled")) + .withStyle(enabledCount > 0 ? ChatFormatting.GREEN : ChatFormatting.RED)); ChatUtils.addChatMessage(stats); } - private static MutableText createClickableText(String displayText, String command, String hoverText, Formatting color) { - return Text.literal(displayText) - .formatted(color) - .styled(style -> style - .withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command)) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - Text.literal(hoverText).formatted(Formatting.GRAY)))); + private static MutableComponent createClickableText(String displayText, String command, String hoverText, ChatFormatting color) { + ClickEvent clickEvent = new ClickEvent.SuggestCommand("." + command); + HoverEvent hoverEvent = new HoverEvent.ShowText(Component.literal(hoverText)); + + return Component.literal(displayText) + .withStyle(color) + .withStyle(style -> style + .withClickEvent(clickEvent) + .withHoverEvent(hoverEvent)); } private static String getShortModName(String fullName) { diff --git a/src/main/java/cn/pupperclient/management/command/impl/BindCommand.java b/src/main/java/cn/pupperclient/management/command/impl/BindCommand.java index d3ae292..049bba0 100644 --- a/src/main/java/cn/pupperclient/management/command/impl/BindCommand.java +++ b/src/main/java/cn/pupperclient/management/command/impl/BindCommand.java @@ -9,16 +9,16 @@ import cn.pupperclient.management.mod.ModManager; import cn.pupperclient.utils.chat.ChatUtils; import cn.pupperclient.utils.language.I18n; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.List; import java.util.Map; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; public class BindCommand { private static final ModManager modManager = PupperClient.getInstance().getModManager(); @@ -138,11 +138,13 @@ private static void listKeybinds() { String keyName = getKeyName(keyCode); for (Mod mod : mods) { - MutableText message = Text.literal("§b• " + mod.getName() + " §7→ §a" + keyName + " §7(keycode: " + keyCode + ")") - .styled(style -> style - .withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, ".bind " + mod.getName() + " none")) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - Text.literal("Click to clear this keybind").formatted(Formatting.GRAY)))); + MutableComponent message = Component.literal("§b• " + mod.getName() + " §7→ §a" + keyName + " §7(keycode: " + keyCode + ")") + .withStyle(style -> style + .withClickEvent(new ClickEvent.SuggestCommand(".bind " + mod.getName() + " none")) + .withHoverEvent(new HoverEvent.ShowText( + Component.literal("Click to clear this keybind").withStyle(ChatFormatting.GRAY) + )) + ); ChatUtils.addChatMessage(message); boundCount++; diff --git a/src/main/java/cn/pupperclient/management/command/impl/IRCCommand.java b/src/main/java/cn/pupperclient/management/command/impl/IRCCommand.java index dbdb2ec..8a04d67 100644 --- a/src/main/java/cn/pupperclient/management/command/impl/IRCCommand.java +++ b/src/main/java/cn/pupperclient/management/command/impl/IRCCommand.java @@ -2,8 +2,9 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.management.mod.impl.misc.IRCChatMod; +import cn.pupperclient.utils.chat.ChatUtils; import cn.pupperclient.utils.minecraft.interfaces.IMinecraft; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; public class IRCCommand implements IMinecraft { @@ -64,8 +65,8 @@ private static void sendHelp() { } private static void sendMessage(String message) { - if (mc.player != null) { - mc.player.sendMessage(Text.of(message), false); + if (client.player != null) { + ChatUtils.addChatMessage(Component.nullToEmpty(message)); } } } diff --git a/src/main/java/cn/pupperclient/management/command/impl/LoginCommand.java b/src/main/java/cn/pupperclient/management/command/impl/LoginCommand.java index e955d57..065175b 100644 --- a/src/main/java/cn/pupperclient/management/command/impl/LoginCommand.java +++ b/src/main/java/cn/pupperclient/management/command/impl/LoginCommand.java @@ -6,15 +6,15 @@ import cn.pupperclient.utils.thread.Multithreading; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; - import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; +import org.jspecify.annotations.NonNull; public class LoginCommand { @@ -97,9 +97,7 @@ private static void sendCaptcha(String phone) { if (result == null || result.has("code") && result.get("code").getAsInt() != 200) { String errorMsg = result != null && result.has("message") ? result.get("message").getAsString() : "发送验证码失败"; - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c发送验证码失败: " + errorMsg); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c发送验证码失败: " + errorMsg)); return; } @@ -109,9 +107,7 @@ private static void sendCaptcha(String phone) { }); } catch (Exception e) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c发送验证码失败: " + e.getMessage()); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c发送验证码失败: " + e.getMessage())); PupperClient.LOGGER.error("发送验证码失败: {}", e.getMessage(), e); } }); @@ -130,7 +126,7 @@ private static void phoneLoginWithCaptcha(String phone, String captcha) { PupperLogger.info("登录请求URL: {}", url); - JsonObject result = sendPostRequest(url, null); + JsonObject result = sendPostRequest(url); if (result == null || result.has("code") && result.get("code").getAsInt() != 200) { String errorMsg = result != null && result.has("message") ? @@ -139,11 +135,11 @@ private static void phoneLoginWithCaptcha(String phone, String captcha) { ChatUtils.addChatMessage("§c验证码登录失败: " + errorMsg); // 提供重新发送验证码的快捷方式 - MutableText retryText = Text.literal("§7[重新发送验证码]") - .styled(style -> style - .withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, ".login send " + phone)) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - Text.literal("点击重新发送验证码")))); + MutableComponent retryText = Component.literal("§7[重新发送验证码]") + .withStyle(style -> style + .withClickEvent(new ClickEvent.SuggestCommand(".login send " + phone)) + .withHoverEvent(new HoverEvent.ShowText( + Component.literal("点击重新发送验证码")))); ChatUtils.addChatMessage(retryText); }); return; @@ -175,9 +171,7 @@ private static void phoneLoginWithCaptcha(String phone, String captcha) { } } catch (Exception e) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c登录过程出错: " + e.getMessage()); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c登录过程出错: " + e.getMessage())); PupperClient.LOGGER.error("验证码登录失败: {}", e.getMessage(), e); } }); @@ -196,9 +190,7 @@ private static void startQRLogin() { JsonObject keyResult = sendGetRequest(keyUrl); if (keyResult == null || !keyResult.has("data") || keyResult.getAsJsonObject("data").get("code").getAsInt() != 200) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c获取二维码key失败"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c获取二维码key失败")); return; } @@ -209,9 +201,7 @@ private static void startQRLogin() { JsonObject qrResult = sendGetRequest(qrUrl); if (qrResult == null || !qrResult.has("data")) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c生成二维码失败"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c生成二维码失败")); return; } @@ -227,9 +217,7 @@ private static void startQRLogin() { checkQRStatus(qrKey); } catch (Exception e) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c二维码登录失败: " + e.getMessage()); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c二维码登录失败: " + e.getMessage())); PupperClient.LOGGER.error("二维码登录失败: {}", e.getMessage(), e); } }); @@ -256,18 +244,14 @@ private static void checkQRStatus(String qrKey) { int code = checkResult.get("code").getAsInt(); if (code == 800) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c二维码已过期,请重新生成"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c二维码已过期,请重新生成")); return; } else if (code == 801) { // 等待扫码,继续轮询 attempts++; continue; } else if (code == 802) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§6已扫描,请在手机上确认登录"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§6已扫描,请在手机上确认登录")); attempts++; continue; } else if (code == 803) { @@ -292,14 +276,10 @@ private static void checkQRStatus(String qrKey) { attempts++; } - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c二维码登录超时,请重试"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c二维码登录超时,请重试")); } catch (Exception e) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c检查二维码状态失败: " + e.getMessage()); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c检查二维码状态失败: " + e.getMessage())); PupperClient.LOGGER.error("检查二维码状态失败: {}", e.getMessage(), e); } }); @@ -363,9 +343,7 @@ private static void checkLoginStatus() { } }); } else { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c登录状态: 已过期"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c登录状态: 已过期")); currentCookie = null; currentUserId = null; currentNickname = null; @@ -373,15 +351,11 @@ private static void checkLoginStatus() { saveLoginStatus(); } } else { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c登录状态检查失败"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c登录状态检查失败")); } } catch (Exception e) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c检查登录状态失败: " + e.getMessage()); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c检查登录状态失败: " + e.getMessage())); PupperClient.LOGGER.error("检查登录状态失败: {}", e.getMessage(), e); } }); @@ -404,19 +378,13 @@ private static void refreshLogin() { JsonObject result = sendGetRequestWithCookie(refreshUrl); if (result != null && result.get("code").getAsInt() == 200) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§a登录状态刷新成功"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§a登录状态刷新成功")); } else { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c登录状态刷新失败"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c登录状态刷新失败")); } } catch (Exception e) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c刷新登录状态失败: " + e.getMessage()); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c刷新登录状态失败: " + e.getMessage())); PupperClient.LOGGER.error("刷新登录状态失败: {}", e.getMessage(), e); } }); @@ -443,14 +411,10 @@ private static void logout() { currentPhone = null; saveLoginStatus(); - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§a已退出登录"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§a已退出登录")); } catch (Exception e) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c退出登录失败: " + e.getMessage()); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c退出登录失败: " + e.getMessage())); PupperClient.LOGGER.error("退出登录失败: {}", e.getMessage(), e); } }); @@ -541,51 +505,21 @@ private static String buildKeyword(String[] args, int startIndex) { return keyword.toString(); } - /** - * 发送GET请求 - */ private static JsonObject sendGetRequest(String urlString) throws IOException { - return sendRequest(urlString, "GET", null, false); + return sendRequest(urlString, "GET", false); } - /** - * 发送带Cookie的GET请求 - */ private static JsonObject sendGetRequestWithCookie(String urlString) throws IOException { - return sendRequest(urlString, "GET", null, true); + return sendRequest(urlString, "GET", true); } - /** - * 发送POST请求 - */ - private static JsonObject sendPostRequest(String urlString, String postData) throws IOException { - return sendRequest(urlString, "POST", postData, false); + private static JsonObject sendPostRequest(String urlString) throws IOException { + return sendRequest(urlString, "POST", false); } - /** - * 通用请求方法 - */ - private static JsonObject sendRequest(String urlString, String method, String postData, boolean useCookie) throws IOException { + private static JsonObject sendRequest(String urlString, String method, boolean useCookie) throws IOException { URL url = new URL(urlString); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod(method); - connection.setConnectTimeout(10000); - connection.setReadTimeout(10000); - connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"); - - // 如果使用cookie且当前有登录状态,添加cookie - if (useCookie && currentCookie != null) { - connection.setRequestProperty("Cookie", currentCookie); - } - - if ("POST".equals(method) && postData != null) { - connection.setDoOutput(true); - connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - try (OutputStream os = connection.getOutputStream()) { - byte[] input = postData.getBytes(StandardCharsets.UTF_8); - os.write(input, 0, input.length); - } - } + HttpURLConnection connection = getHttpURLConnection(method, useCookie, url); int responseCode = connection.getResponseCode(); if (responseCode != 200) { @@ -605,33 +539,35 @@ private static JsonObject sendRequest(String urlString, String method, String po } } - /** - * 获取当前cookie(供MusicCommand使用) - */ + private static @NonNull HttpURLConnection getHttpURLConnection(String method, boolean useCookie, URL url) throws IOException { + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(method); + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"); + + if (useCookie && currentCookie != null) { + connection.setRequestProperty("Cookie", currentCookie); + } + + return connection; + } + public static String getCurrentCookie() { if (currentCookie == null) { - loadLoginStatus(); // 尝试加载保存的登录状态 + loadLoginStatus(); } return currentCookie; } - /** - * 获取当前用户ID - */ public static String getCurrentUserId() { return currentUserId; } - /** - * 获取当前昵称 - */ public static String getCurrentNickname() { return currentNickname; } - /** - * 获取当前手机号 - */ public static String getCurrentPhone() { return currentPhone; } diff --git a/src/main/java/cn/pupperclient/management/command/impl/MusicCommand.java b/src/main/java/cn/pupperclient/management/command/impl/MusicCommand.java index 46efbda..cedf324 100644 --- a/src/main/java/cn/pupperclient/management/command/impl/MusicCommand.java +++ b/src/main/java/cn/pupperclient/management/command/impl/MusicCommand.java @@ -7,12 +7,6 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.utils.chat.ChatUtils; import cn.pupperclient.utils.thread.Multithreading; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; - import java.io.*; import java.net.HttpURLConnection; import java.net.URL; @@ -20,6 +14,11 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; public class MusicCommand { @@ -157,18 +156,18 @@ private static void searchMusic(String keyword, int limit) { } // 格式化显示 - MutableText songText = Text.literal("§b" + (i + 1) + ". §f" + songName) - .styled(style -> style - .withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, ".music download " + songId)) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - Text.literal("§6点击快速下载\n§7歌手: " + artistsStr + "\n§7专辑: " + albumName)))); - - MutableText artistText = Text.literal(" §7- " + artistsStr); - MutableText downloadBtn = createClickableText( + MutableComponent songText = Component.literal("§b" + (i + 1) + ". §f" + songName) + .withStyle(style -> style + .withClickEvent(new ClickEvent.SuggestCommand(".music download " + songId)) + .withHoverEvent(new HoverEvent.ShowText( + Component.literal("§6点击快速下载\n§7歌手: " + artistsStr + "\n§7专辑: " + albumName)))); + + MutableComponent artistText = Component.literal(" §7- " + artistsStr); + MutableComponent downloadBtn = createClickableText( ".music download " + songId, "下载 " + songName); - MutableText fullLine = Text.empty() + MutableComponent fullLine = Component.empty() .append(songText) .append(artistText) .append(downloadBtn); @@ -195,9 +194,7 @@ private static void downloadMusic(String songId, String quality) { if (checkResult == null || !checkResult.get("success").getAsBoolean()) { String message = checkResult != null ? checkResult.get("message").getAsString() : "检查失败"; - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c音乐不可用: " + message); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c音乐不可用: " + message)); return; } @@ -205,25 +202,19 @@ private static void downloadMusic(String songId, String quality) { JsonObject urlResult = sendGetRequest(urlApi); if (urlResult == null || !urlResult.has("data")) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c获取音乐URL失败"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c获取音乐URL失败")); return; } JsonArray data = urlResult.getAsJsonArray("data"); if (data.isEmpty() || data.get(0).getAsJsonObject().get("url") == null) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c该音质暂不可用,请尝试其他音质"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c该音质暂不可用,请尝试其他音质")); return; } String musicUrl = data.get(0).getAsJsonObject().get("url").getAsString(); if (musicUrl == null || musicUrl.isEmpty()) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c获取音乐链接失败"); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c获取音乐链接失败")); return; } @@ -287,9 +278,7 @@ private static void downloadMusic(String songId, String quality) { }); } catch (Exception e) { - Multithreading.runMainThread(() -> { - ChatUtils.addChatMessage("§c下载失败: " + e.getMessage()); - }); + Multithreading.runMainThread(() -> ChatUtils.addChatMessage("§c下载失败: " + e.getMessage())); PupperClient.LOGGER.error("音乐下载失败: {}", e.getMessage(), e); } }); @@ -333,7 +322,7 @@ private static void listDownloadedMusic() { return; } - File[] musicFiles = MUSIC_DIR.listFiles((dir, name) -> + File[] musicFiles = MUSIC_DIR.listFiles((_, name) -> name.toLowerCase().endsWith(".mp3") || name.toLowerCase().endsWith(".flac")); if (musicFiles == null || musicFiles.length == 0) { @@ -348,10 +337,10 @@ private static void listDownloadedMusic() { String fileName = musicFile.getName(); String displayName = fileName.substring(0, fileName.lastIndexOf('.')); - MutableText fileText = Text.literal("§b" + (i + 1) + ". §f" + displayName) - .styled(style -> style - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - Text.literal("§6文件: " + fileName + "\n§7大小: " + formatFileSize(musicFile.length()))))); + MutableComponent fileText = Component.literal("§b" + (i + 1) + ". §f" + displayName) + .withStyle(style -> style + .withHoverEvent(new HoverEvent.ShowText( + Component.literal("§6文件: " + fileName + "\n§7大小: " + formatFileSize(musicFile.length()))))); ChatUtils.addChatMessage(fileText); } @@ -449,8 +438,7 @@ private static boolean downloadFile(String fileUrl, File outputFile) { outputStream.write(buffer, 0, bytesRead); totalRead += bytesRead; - // 可以在这里添加进度显示(可选) - if (fileSize > 0 && totalRead % (1024 * 1024) == 0) { // 每MB更新一次 + if (fileSize > 0 && totalRead % (1024 * 1024) == 0) { int progress = (int) ((totalRead * 100) / fileSize); ChatUtils.addChatMessage("§7下载进度: " + progress + "%"); } @@ -481,12 +469,12 @@ private static String formatFileSize(long size) { } } - private static MutableText createClickableText(String command, String hoverText) { - return Text.literal(" [下载]") - .formatted(Formatting.GREEN) - .styled(style -> style - .withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command)) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - Text.literal(hoverText).formatted(Formatting.GRAY)))); + private static MutableComponent createClickableText(String command, String hoverText) { + return Component.literal(" [下载]") + .withStyle(ChatFormatting.GREEN) + .withStyle(style -> style + .withClickEvent(new ClickEvent.SuggestCommand(command)) + .withHoverEvent(new HoverEvent.ShowText( + Component.literal(hoverText).withStyle(ChatFormatting.GRAY)))); } } diff --git a/src/main/java/cn/pupperclient/management/config/impl/ModConfig.java b/src/main/java/cn/pupperclient/management/config/impl/ModConfig.java index 9784179..918d3b1 100644 --- a/src/main/java/cn/pupperclient/management/config/impl/ModConfig.java +++ b/src/main/java/cn/pupperclient/management/config/impl/ModConfig.java @@ -6,6 +6,7 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.management.mod.impl.hud.DynamicIsland; import com.google.gson.JsonObject; +import com.mojang.blaze3d.platform.InputConstants; import cn.pupperclient.libraries.material3.hct.Hct; import cn.pupperclient.management.config.Config; import cn.pupperclient.management.config.ConfigType; @@ -19,8 +20,6 @@ import cn.pupperclient.utils.color.ColorUtils; import cn.pupperclient.utils.misc.JsonUtils; -import net.minecraft.client.util.InputUtil; - public class ModConfig extends Config { public ModConfig() { @@ -160,10 +159,10 @@ private void loadKeybindSetting(KeybindSetting setting, JsonObject settingsJson) String inputType = JsonUtils.getStringProperty(keybindJson, "type", ""); int keyCode = JsonUtils.getIntProperty(keybindJson, "code", -1); - InputUtil.Type type = determineInputType(inputType); + InputConstants.Type type = determineInputType(inputType); if (!inputType.isEmpty() && keyCode != -1) { - setting.setKey(type.createFromCode(keyCode)); + setting.setKey(type.getOrCreate(keyCode)); } else { setting.setKey(setting.getDefaultKey()); } @@ -264,11 +263,11 @@ private void saveHctColorSetting(HctColorSetting setting, JsonObject settingsJso private void saveKeybindSetting(KeybindSetting setting, JsonObject settingsJson) { JsonObject keybindJson = new JsonObject(); - InputUtil.Type type = setting.getKey().getCategory(); + InputConstants.Type type = setting.getKey().getType(); String saveType = getInputTypeString(type); keybindJson.addProperty("type", saveType); - keybindJson.addProperty("code", setting.getKey().getCode()); + keybindJson.addProperty("code", setting.getKey().getValue()); settingsJson.add(setting.getName(), keybindJson); } @@ -287,18 +286,18 @@ private void saveFileSetting(FileSetting setting, JsonObject settingsJson) { settingsJson.addProperty(setting.getName(), filePath); } - private InputUtil.Type determineInputType(String inputType) { + private InputConstants.Type determineInputType(String inputType) { return switch (inputType) { - case "key" -> InputUtil.Type.KEYSYM; - case "mouse" -> InputUtil.Type.MOUSE; - default -> InputUtil.Type.SCANCODE; + case "key" -> InputConstants.Type.KEYSYM; + case "mouse" -> InputConstants.Type.MOUSE; + default -> InputConstants.Type.SCANCODE; }; } - private String getInputTypeString(InputUtil.Type type) { - if (type.equals(InputUtil.Type.KEYSYM)) { + private String getInputTypeString(InputConstants.Type type) { + if (type.equals(InputConstants.Type.KEYSYM)) { return "key"; - } else if (type.equals(InputUtil.Type.MOUSE)) { + } else if (type.equals(InputConstants.Type.MOUSE)) { return "mouse"; } else { return "scancode"; diff --git a/src/main/java/cn/pupperclient/management/keybind/KeybindManager.java b/src/main/java/cn/pupperclient/management/keybind/KeybindManager.java index 3045dec..1a7a8fe 100644 --- a/src/main/java/cn/pupperclient/management/keybind/KeybindManager.java +++ b/src/main/java/cn/pupperclient/management/keybind/KeybindManager.java @@ -114,8 +114,7 @@ public int getPriority() { private void handleGlobalKeyEvent(KeyEvent event) { if (!event.isState()) return; - // 防止在GUI界面中误触发 - if (mc != null && mc.currentScreen != null) return; + if (client.screen != null) return; int keyCode = event.getKeybind(); List mods = getModsByKey(keyCode); @@ -123,7 +122,6 @@ private void handleGlobalKeyEvent(KeyEvent event) { if (!mods.isEmpty()) { LOGGER.debug("Keybind triggered: {} for {} mod(s)", keyCode, mods.size()); - // 触发所有绑定到此按键的Mod for (Mod mod : mods) { LOGGER.debug("Toggling mod: {}", mod.getName()); mod.toggle(); diff --git a/src/main/java/cn/pupperclient/management/mod/api/Position.java b/src/main/java/cn/pupperclient/management/mod/api/Position.java index e863ed2..41eadf8 100644 --- a/src/main/java/cn/pupperclient/management/mod/api/Position.java +++ b/src/main/java/cn/pupperclient/management/mod/api/Position.java @@ -1,6 +1,6 @@ package cn.pupperclient.management.mod.api; -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; public class Position { @@ -121,11 +121,11 @@ private float getAnchorY(float value) { } private float getScreenWidth() { - return MinecraftClient.getInstance().getWindow().getScaledWidth(); + return Minecraft.getInstance().getWindow().getGuiScaledWidth(); } private float getScreenHeight() { - return MinecraftClient.getInstance().getWindow().getScaledHeight(); + return Minecraft.getInstance().getWindow().getGuiScaledHeight(); } public float getScale() { diff --git a/src/main/java/cn/pupperclient/management/mod/api/hud/SimpleListHUDMod.java b/src/main/java/cn/pupperclient/management/mod/api/hud/SimpleListHUDMod.java index eaf072f..395ee13 100644 --- a/src/main/java/cn/pupperclient/management/mod/api/hud/SimpleListHUDMod.java +++ b/src/main/java/cn/pupperclient/management/mod/api/hud/SimpleListHUDMod.java @@ -13,13 +13,11 @@ public SimpleListHUDMod (String name, String description, String icon) { } protected void draw() { - float fontSize = 9; float padding = 5; float maxWidth = 0; float height = 0; - float lineHeight = 5; // 空行的间隔 - // EN: Line height spacing + float lineHeight = 5; for (int i = 0; i < getText().size(); i++) { Rect textBounds = Skia.getTextBounds(getText().get(i), Fonts.getRegular(fontSize)); diff --git a/src/main/java/cn/pupperclient/management/mod/impl/fun/FakeFpsMod.java b/src/main/java/cn/pupperclient/management/mod/impl/fun/FakeFpsMod.java index 83fd095..263665e 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/fun/FakeFpsMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/fun/FakeFpsMod.java @@ -1,16 +1,15 @@ package cn.pupperclient.management.mod.impl.fun; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.management.mod.settings.impl.ComboSetting; import cn.pupperclient.management.mod.settings.impl.NumberSetting; import cn.pupperclient.skia.font.Icon; -import net.minecraft.client.MinecraftClient; - import java.util.Arrays; import java.util.List; import java.util.Random; +import net.minecraft.client.Minecraft; public class FakeFpsMod extends SimpleHUDMod { private final ComboSetting modeSetting; @@ -79,7 +78,7 @@ public FakeFpsMod() { @Override public String getText() { - int realFps = MinecraftClient.getInstance().getCurrentFps(); + int realFps = Minecraft.getInstance().getFps(); String mode = modeSetting.getOption(); switch (mode) { diff --git a/src/main/java/cn/pupperclient/management/mod/impl/fun/HeypixelMod.java b/src/main/java/cn/pupperclient/management/mod/impl/fun/HeypixelMod.java index ac82b86..667e225 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/fun/HeypixelMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/fun/HeypixelMod.java @@ -9,7 +9,7 @@ import cn.pupperclient.management.mod.settings.impl.BooleanSetting; import cn.pupperclient.skia.font.Icon; import cn.pupperclient.utils.chat.ChatUtils; -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; public class HeypixelMod extends Mod { private static HeypixelMod instance; @@ -55,9 +55,9 @@ public void onChatMessage(ChatEvent event) { ChatUtils.addChatMessage("checked! try to send /again command"); } EventBus.getInstance().post(new AutoAgainEvent()); - MinecraftClient client = MinecraftClient.getInstance(); + Minecraft client = Minecraft.getInstance(); if (client.player != null) { - client.player.networkHandler.sendChatCommand("again"); + client.player.connection.sendCommand("again"); if (Logging.isEnabled()) { ChatUtils.addChatMessage("Done"); } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/fun/TotemTracker.java b/src/main/java/cn/pupperclient/management/mod/impl/fun/TotemTracker.java index b8a3b29..5981d65 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/fun/TotemTracker.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/fun/TotemTracker.java @@ -8,14 +8,13 @@ import cn.pupperclient.management.mod.ModCategory; import cn.pupperclient.skia.font.Icon; import cn.pupperclient.utils.chat.ChatUtils; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityStatuses; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; - import java.util.HashMap; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityEvent; +import net.minecraft.world.entity.player.Player; public class TotemTracker extends Mod { private static TotemTracker instance; @@ -42,40 +41,41 @@ public void onDisable() { @EventListener public void onTotem(TotemEvent event) { - PlayerEntity player = event.getPlayer(); + Player player = event.getPlayer(); char ch = 0; int l_Count = 1; if (popContainer.containsKey(player.getName().getString())) { l_Count = popContainer.get(player.getName().getString()); } if (l_Count == 1) { - if (player.equals(mc.player)) { - ChatUtils.addChatMessage(Text.of(String.format(Formatting.WHITE + "You(%s)" + Formatting.RESET + " popped " + Formatting.GRAY + "%d" + Formatting.RESET + " totem.", player.getName().getString(), l_Count))); + if (player.equals(client.player)) { + ChatUtils.addChatMessage(Component.nullToEmpty(String.format(ChatFormatting.WHITE + "You(%s)" + ChatFormatting.RESET + " popped " + ChatFormatting.GRAY + "%d" + ChatFormatting.RESET + " totem.", player.getName().getString(), l_Count))); } else { - ChatUtils.addChatMessage(Text.of(String.format(Formatting.WHITE + "%s" + Formatting.RESET + " popped " + Formatting.GRAY + "%d" + Formatting.RESET + " totem.", player.getName().getString().replace(String.valueOf(Formatting.FORMATTING_CODE_PREFIX), ""), l_Count))); + ChatUtils.addChatMessage(Component.nullToEmpty(String.format(ChatFormatting.WHITE + "%s" + ChatFormatting.RESET + " popped " + ChatFormatting.GRAY + "%d" + ChatFormatting.RESET + " totem.", player.getName().getString().replace(String.valueOf(ChatFormatting.PREFIX_CODE), ""), l_Count))); } } else { - if (player.equals(mc.player)) { - ChatUtils.addChatMessage(Text.of(String.format(Formatting.WHITE + "You(%s)" + Formatting.RESET + " popped " + Formatting.GRAY + "%d" + Formatting.RESET + " totem.", player.getName().getString().replace(String.valueOf(Formatting.FORMATTING_CODE_PREFIX), ""), l_Count))); + if (player.equals(client.player)) { + ChatUtils.addChatMessage(Component.nullToEmpty(String.format(ChatFormatting.WHITE + "You(%s)" + ChatFormatting.RESET + " popped " + ChatFormatting.GRAY + "%d" + ChatFormatting.RESET + " totem.", player.getName().getString().replace(String.valueOf(ChatFormatting.PREFIX_CODE), ""), l_Count))); } else { - ChatUtils.addChatMessage(Text.of(String.format(Formatting.WHITE + "%s" + Formatting.RESET + " has popped " + Formatting.GRAY + "%d" + Formatting.RESET + " totems.", player.getName().getString(), l_Count))); + ChatUtils.addChatMessage(Component.nullToEmpty(String.format(ChatFormatting.WHITE + "%s" + ChatFormatting.RESET + " has popped " + ChatFormatting.GRAY + "%d" + ChatFormatting.RESET + " totems.", player.getName().getString(), l_Count))); } } } - @EventListener(priority = 1001) + @EventListener(priority = EventListener.Priority.HIGHEST) public void onPacketReceive(ReceivePacketEvent event) { - if (event.getPacket() instanceof EntityStatusS2CPacket packet) { - if (packet.getStatus() == EntityStatuses.USE_TOTEM_OF_UNDYING) { - Entity entity = packet.getEntity(mc.world); - if(entity instanceof PlayerEntity player) { + if (event.getPacket() instanceof ClientboundEntityEventPacket packet) { + if (packet.getEventId() == EntityEvent.PROTECTED_FROM_DEATH) { + assert client.level != null; + Entity entity = packet.getEntity(client.level); + if(entity instanceof Player player) { onTotemPop(player); } } } } - public void onTotemPop(PlayerEntity player) { + public void onTotemPop(Player player) { int l_Count = 1; if (popContainer.containsKey(player.getName().getString())) { l_Count = popContainer.get(player.getName().getString()); diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/ArrayListMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/ArrayListMod.java index 85bc3e9..139ba72 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/ArrayListMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/ArrayListMod.java @@ -3,15 +3,12 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.event.EventBus; import cn.pupperclient.event.EventListener; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.libraries.material3.hct.Hct; -import cn.pupperclient.libraries.material3.hct.HctSolver; import cn.pupperclient.management.mod.Mod; import cn.pupperclient.management.mod.ModCategory; import cn.pupperclient.management.mod.api.hud.HUDMod; import cn.pupperclient.event.mod.ModStateChangeEvent; -import cn.pupperclient.management.mod.api.hud.design.HUDDesign; -import cn.pupperclient.management.mod.impl.settings.HUDModSettings; import cn.pupperclient.management.mod.impl.settings.ModMenuSettings; import cn.pupperclient.management.mod.settings.impl.BooleanSetting; import cn.pupperclient.management.mod.settings.impl.ComboSetting; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/BedwarsStatsOverlayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/BedwarsStatsOverlayMod.java index 2f0e437..5c7a09b 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/BedwarsStatsOverlayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/BedwarsStatsOverlayMod.java @@ -1,10 +1,12 @@ package cn.pupperclient.management.mod.impl.hud; import java.io.File; +import java.util.Objects; +import net.minecraft.client.multiplayer.PlayerInfo; import cn.pupperclient.PupperClient; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.hypixel.api.HypixelUser; import cn.pupperclient.management.mod.api.hud.HUDMod; import cn.pupperclient.management.mod.settings.impl.NumberSetting; @@ -15,8 +17,6 @@ import cn.pupperclient.utils.server.Server; import cn.pupperclient.utils.server.ServerUtils; -import net.minecraft.client.network.PlayerListEntry; - public class BedwarsStatsOverlayMod extends HUDMod { private NumberSetting maxSetting = new NumberSetting("setting.max", "setting.max.description", Icon.MAXIMIZE, this, @@ -46,28 +46,22 @@ public BedwarsStatsOverlayMod() { if (ServerUtils.isJoin(Server.HYPIXEL)) { - for (PlayerListEntry player : mc.getNetworkHandler().getPlayerList()) { - - if (player.getProfile() == null) { - continue; - } + for (PlayerInfo player : Objects.requireNonNull(client.getConnection()).getOnlinePlayers()) { - String name = player.getProfile().getName(); - String uuid = player.getProfile().getId().toString().replace("-", ""); + String name = player.getProfile().name(); + String uuid = player.getProfile().id().toString().replace("-", ""); HypixelUser hypixelUser = PupperClient.getInstance().getHypixelManager().getByUuid(uuid); if (hypixelUser != null) { - if (player.getSkinTextures() != null) { + player.getSkin(); + File file = SkinUtils.getSkin(player.getSkin().body().texturePath()); - File file = SkinUtils.getSkin(player.getSkinTextures().texture()); - - if (file.exists()) { - Skia.drawPlayerHead(file, getX() + 5.5F, getY() + offsetY, 12, 12, 2.5F); - } - } + if (file.exists()) { + Skia.drawPlayerHead(file, getX() + 5.5F, getY() + offsetY, 12, 12, 2.5F); + } - Skia.drawHeightCenteredText(name, getX() + 21, getY() + offsetY + 6F, + Skia.drawHeightCenteredText(name, getX() + 21, getY() + offsetY + 6F, this.getDesign().getTextColor(), Fonts.getRegular(9)); Skia.drawFullCenteredText(hypixelUser.getBedwarsLevel(), getX() + 120, getY() + offsetY + 6F, diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/CPSDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/CPSDisplayMod.java index 5ebf24c..3a68bf9 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/CPSDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/CPSDisplayMod.java @@ -6,7 +6,7 @@ import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.ClientTickEvent; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.management.mod.settings.impl.BooleanSetting; import cn.pupperclient.skia.Skia; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/ClockMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/ClockMod.java index 3a41a0c..13b3607 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/ClockMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/ClockMod.java @@ -6,7 +6,7 @@ import java.util.Locale; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/CloudMusicHudMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/CloudMusicHudMod.java index e6db92a..d4502cd 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/CloudMusicHudMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/CloudMusicHudMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventListener; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.management.mod.settings.impl.ComboSetting; import cn.pupperclient.skia.Skia; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/ComboCounterMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/ComboCounterMod.java index 0968b1e..70637b2 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/ComboCounterMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/ComboCounterMod.java @@ -2,7 +2,7 @@ import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.ClientTickEvent; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.event.server.impl.AttackEntityEvent; import cn.pupperclient.event.server.impl.DamageEntityEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; @@ -31,7 +31,7 @@ public ComboCounterMod() { combo++; possibleTarget = -1; hitTime = System.currentTimeMillis(); - } else if (event.getEntityId() == mc.player.getId()) { + } else if (event.getEntityId() == client.player.getId()) { combo = 0; } }; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/CooldownHudMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/CooldownHudMod.java index becc135..a1ebba3 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/CooldownHudMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/CooldownHudMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventListener; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; public class CooldownHudMod extends SimpleHUDMod { @@ -27,8 +27,8 @@ public void onSkiaRender(RenderSkiaEvent event) { @Override public String getText() { float cooldownProgress = 0; - if (mc.player != null) { - cooldownProgress = mc.player.getAttackCooldownProgress(0.0F); + if (client.player != null) { + cooldownProgress = client.player.getAttackStrengthScale(0.0F); } boolean isCooldown = cooldownProgress < 1.0f; return isCooldown ? ("Cooldown: " + cooldownProgress) : "Done"; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/CoordsMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/CoordsMod.java index 7f58544..998cd83 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/CoordsMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/CoordsMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; @@ -17,9 +17,9 @@ public CoordsMod() { @Override public String getText() { - if (mc.player != null) { - return "X: " + (int) mc.player.getX() + " Y: " + (int) mc.player.getY() + " Z: " - + (int) mc.player.getZ(); + if (client.player != null) { + return "X: " + (int) client.player.getX() + " Y: " + (int) client.player.getY() + " Z: " + + (int) client.player.getZ(); } return ""; } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/DayCounterMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/DayCounterMod.java index 21b570c..c1b64b5 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/DayCounterMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/DayCounterMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; @@ -17,7 +17,7 @@ public DayCounterMod() { @Override public String getText() { - long time = mc.world.getTime() / 24000L; + long time = client.level.getGameTime() / 24000L; return time + " Day" + (time > 1L ? "s" : ""); } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/DynamicIsland.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/DynamicIsland.java index b001f60..070729f 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/DynamicIsland.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/DynamicIsland.java @@ -2,7 +2,7 @@ import cn.pupperclient.event.EventBus; import cn.pupperclient.event.EventListener; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.event.mod.AutoAgainEvent; import cn.pupperclient.management.mod.api.hud.HUDMod; import cn.pupperclient.event.mod.ModStateChangeEvent; @@ -205,7 +205,7 @@ private void drawNormalTextWithIcons(float startX, float startY, float fontSize, drawTextWithAlpha(playerIcon, currentX, startY, Fonts.getIcon(iconSize), (float) 1.0); currentX += Skia.getTextBounds(playerIcon, Fonts.getIcon(iconSize)).getWidth() + 2; - String playerName = mc.player != null ? mc.player.getName().getString() : "NULL"; + String playerName = client.player != null ? client.player.getName().getString() : "NULL"; drawTextWithAlpha(playerName + " · ", currentX, startY, Fonts.getGoogleSansRegular(fontSize), (float) 1.0); currentX += Skia.getTextBounds(playerName + " · ", Fonts.getGoogleSansRegular(fontSize)).getWidth() + 5; @@ -223,7 +223,7 @@ private void drawNormalTextWithIcons(float startX, float startY, float fontSize, drawTextWithAlpha(fpsIcon, currentX, startY - 1F, Fonts.getIcon(iconSize), (float) 1.0); currentX += Skia.getTextBounds(fpsIcon, Fonts.getIcon(iconSize)).getWidth() + 2; - String fpsText = mc.getCurrentFps() + " FPS"; + String fpsText = client.getFps() + " FPS"; drawTextWithAlpha(fpsText, currentX, startY, Fonts.getGoogleSansRegular(fontSize), (float) 1.0); } @@ -236,7 +236,7 @@ private float calculateNormalTextWidth(float fontSize, float iconSize) { // 玩家图标和名称 String playerIcon = Icon.PERSON; totalWidth += Skia.getTextBounds(playerIcon, Fonts.getIcon(iconSize)).getWidth() + 2; - String playerName = mc.player != null ? mc.player.getName().getString() : "NULL"; + String playerName = client.player != null ? client.player.getName().getString() : "NULL"; totalWidth += Skia.getTextBounds(playerName + " · ", Fonts.getGoogleSansRegular(fontSize)).getWidth() + 5; // 服务器信息和延迟 @@ -248,7 +248,7 @@ private float calculateNormalTextWidth(float fontSize, float iconSize) { // FPS图标和数值 String fpsIcon = Icon.DESKTOP_WINDOWS; totalWidth += Skia.getTextBounds(fpsIcon, Fonts.getIcon(iconSize)).getWidth() + 2; - String fpsText = mc.getCurrentFps() + " FPS"; + String fpsText = client.getFps() + " FPS"; totalWidth += Skia.getTextBounds(fpsText, Fonts.getGoogleSansRegular(fontSize)).getWidth() + 5; return totalWidth; @@ -329,9 +329,9 @@ private float easeInCubic(float x) { } private @NotNull String getServerInfo() { - if (mc.getCurrentServerEntry() != null && mc.player != null) { - String serverAddress = mc.getCurrentServerEntry().address; - long ping = mc.getCurrentServerEntry().ping; + if (client.getCurrentServer() != null && client.player != null) { + String serverAddress = client.getCurrentServer().ip; + long ping = client.getCurrentServer().ping; return ping + "ms to " + serverAddress; } return "Singleplayer"; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/FPSDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/FPSDisplayMod.java index 6b0322e..c57a969 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/FPSDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/FPSDisplayMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; @@ -17,7 +17,7 @@ public FPSDisplayMod() { @Override public String getText() { - return mc.getCurrentFps() + " FPS"; + return client.getFps() + " FPS"; } @Override diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/FallDamageHelp.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/FallDamageHelp.java index 3e0c10f..845d7bd 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/FallDamageHelp.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/FallDamageHelp.java @@ -1,17 +1,17 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; -import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.util.shape.VoxelShapes; -import net.minecraft.world.World; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; public class FallDamageHelp extends SimpleHUDMod { public FallDamageHelp() { @@ -23,19 +23,19 @@ public FallDamageHelp() { }; public static boolean willFallToDeath() { - MinecraftClient client = MinecraftClient.getInstance(); - ClientPlayerEntity player = client.player; + Minecraft client = Minecraft.getInstance(); + LocalPlayer player = client.player; if (player == null) { return false; } - World world = player.getEntityWorld(); + Level world = player.level(); double currentY = player.getY(); - BlockPos playerBlockPos = player.getBlockPos(); + BlockPos playerBlockPos = player.blockPosition(); for (int offset = 1; offset < 256; offset++) { int y = playerBlockPos.getY() - offset; - if (y < world.getBottomY()) { + if (y < world.getMinY()) { break; } @@ -43,14 +43,14 @@ public static boolean willFallToDeath() { BlockState state = world.getBlockState(checkPos); VoxelShape collisionShape = state.getCollisionShape(world, checkPos); - if (!collisionShape.isEmpty() && collisionShape != VoxelShapes.empty()) { - double blockTopY = y + collisionShape.getMax(Direction.Axis.Y); + if (!collisionShape.isEmpty() && collisionShape != Shapes.empty()) { + double blockTopY = y + collisionShape.max(Direction.Axis.Y); double fallDistance = currentY - blockTopY; return fallDistance >= 23; } } - double fallDistance = currentY - world.getBottomY(); + double fallDistance = currentY - world.getMinY(); return fallDistance >= 23; } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/GameModeDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/GameModeDisplayMod.java index 23ff1a1..aea52ac 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/GameModeDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/GameModeDisplayMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; @@ -20,9 +20,9 @@ public String getText() { String prefix = "Mode: "; - if (mc.player.isCreative()) { + if (client.player.isCreative()) { return prefix + "Creative"; - } else if (mc.player.isSpectator()) { + } else if (client.player.isSpectator()) { return prefix + "Spectator"; } else { return prefix + "Survival"; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/HealthDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/HealthDisplayMod.java index f703d7d..5add4f9 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/HealthDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/HealthDisplayMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; @@ -17,8 +17,8 @@ public HealthDisplayMod() { @Override public String getText() { - if (mc.player != null) { - return (int) mc.player.getHealth() + " Health"; + if (client.player != null) { + return (int) client.player.getHealth() + " Health"; } return ""; } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/JumpResetIndicatorMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/JumpResetIndicatorMod.java index 4faad98..cf4b7ac 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/JumpResetIndicatorMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/JumpResetIndicatorMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.management.mod.settings.impl.NumberSetting; import cn.pupperclient.skia.font.Icon; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/KeystrokesMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/KeystrokesMod.java index ee4a86e..fa52673 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/KeystrokesMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/KeystrokesMod.java @@ -2,13 +2,13 @@ import java.util.ArrayList; import java.util.List; - +import net.minecraft.client.KeyMapping; import cn.pupperclient.animation.Animation; import cn.pupperclient.animation.Duration; import cn.pupperclient.animation.cubicbezier.impl.EaseStandard; import cn.pupperclient.animation.other.DummyAnimation; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.HUDMod; import cn.pupperclient.management.mod.impl.settings.HUDModSettings; import cn.pupperclient.management.mod.settings.impl.BooleanSetting; @@ -18,8 +18,6 @@ import cn.pupperclient.skia.font.Icon; import cn.pupperclient.utils.color.ColorUtils; -import net.minecraft.client.option.KeyBinding; - public class KeystrokesMod extends HUDMod { private List panels = new ArrayList<>(); @@ -34,11 +32,11 @@ public class KeystrokesMod extends HUDMod { public KeystrokesMod() { super("mod.keystrokes.name", "mod.keystrokes.description", Icon.KEYBOARD); - panels.add(new Panel(mc.options.forwardKey, 32, 0)); - panels.add(new Panel(mc.options.leftKey, 0, 32)); - panels.add(new Panel(mc.options.backKey, 32, 32)); - panels.add(new Panel(mc.options.rightKey, 64, 32)); - panels.add(new Panel(mc.options.jumpKey, 0, 64, 92, 22, true)); + panels.add(new Panel(client.options.keyUp, 32, 0)); + panels.add(new Panel(client.options.keyLeft, 0, 32)); + panels.add(new Panel(client.options.keyDown, 32, 32)); + panels.add(new Panel(client.options.keyRight, 64, 32)); + panels.add(new Panel(client.options.keyJump, 0, 64, 92, 22, true)); } @Override @@ -88,11 +86,11 @@ public float getRadius() { private class Panel { private float x, y, width, height; - private KeyBinding keyBinding; + private KeyMapping keyBinding; private boolean jumpKey; private Animation animation; - private Panel(KeyBinding keyBinding, float x, float y, float width, float height, boolean jumpKey) { + private Panel(KeyMapping keyBinding, float x, float y, float width, float height, boolean jumpKey) { this.x = x; this.y = y; this.width = width; @@ -102,7 +100,7 @@ private Panel(KeyBinding keyBinding, float x, float y, float width, float height this.animation = new DummyAnimation(0); } - private Panel(KeyBinding keyBinding, float x, float y) { + private Panel(KeyMapping keyBinding, float x, float y) { this(keyBinding, x, y, 28, 28, false); } @@ -111,7 +109,7 @@ private void draw() { KeystrokesMod.this.drawBackground(getX() + x, getY() + y, width, height); if (!jumpKey && !unmarkSetting.isEnabled()) { - Skia.drawFullCenteredText(keyBinding.getBoundKeyLocalizedText().getString(), getX() + x + (width / 2), + Skia.drawFullCenteredText(keyBinding.getTranslatedKeyMessage().getString(), getX() + x + (width / 2), getY() + y + (height / 2), KeystrokesMod.this.getDesign().getTextColor(), Fonts.getRegular(12)); } @@ -138,10 +136,10 @@ private void drawBlur() { private void update() { - boolean isKeyDown = snapTapSetting.isEnabled() ? keyBinding.isPressed() + boolean isKeyDown = snapTapSetting.isEnabled() ? keyBinding.isDown() : ((IMixinKeyBinding) keyBinding).getRealIsPressed(); - if (isKeyDown && animation.getEnd() != 1 && mc.currentScreen == null) { + if (isKeyDown && animation.getEnd() != 1 && client.screen == null) { animation = new EaseStandard(Duration.MEDIUM_3, animation.getValue(), 1); } else if (!isKeyDown && animation.getEnd() != 0) { animation = new EaseStandard(Duration.MEDIUM_3, animation.getValue(), 0); diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/MemoryUsageMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/MemoryUsageMod.java index 9615ecf..c5604cb 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/MemoryUsageMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/MemoryUsageMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/MouseStrokesMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/MouseStrokesMod.java index b81dd66..a0d08b5 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/MouseStrokesMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/MouseStrokesMod.java @@ -4,12 +4,11 @@ import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.ClientTickEvent; import cn.pupperclient.event.client.PlayerDirectionChangeEvent; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.HUDMod; import cn.pupperclient.skia.Skia; import cn.pupperclient.skia.font.Icon; - -import net.minecraft.util.math.MathHelper; +import net.minecraft.util.Mth; public class MouseStrokesMod extends HUDMod { @@ -47,8 +46,8 @@ public MouseStrokesMod() { public final EventBus.EventListener onPlayerDirectionChange = event -> { mouseX += (event.getYaw() - event.getPrevYaw()) / 7F; mouseY += (event.getPitch() - event.getPrevPitch()) / 7F; - mouseX = MathHelper.clamp(mouseX, -20, 20); - mouseY = MathHelper.clamp(mouseY, -20, 20); + mouseX = Mth.clamp(mouseX, -20, 20); + mouseY = Mth.clamp(mouseY, -20, 20); }; @Override diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/MusicInfoMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/MusicInfoMod.java index 8ab5e75..212b06d 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/MusicInfoMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/MusicInfoMod.java @@ -11,7 +11,7 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.ClientTickEvent; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.gui.edithud.api.HUDCore; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.management.mod.settings.impl.BooleanSetting; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/NameDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/NameDisplayMod.java index dd8cdbc..efb92f2 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/NameDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/NameDisplayMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; @@ -17,7 +17,7 @@ public NameDisplayMod() { @Override public String getText() { - return "Name: " + mc.player.getGameProfile().getName(); + return "Name: " + client.player.getGameProfile().name(); } @Override diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/PingDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/PingDisplayMod.java index 70fdb24..70e908e 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/PingDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/PingDisplayMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.management.mod.settings.impl.NumberSetting; import cn.pupperclient.skia.font.Icon; @@ -35,16 +35,16 @@ private void updatePing() { if (timer.delay((long) (1000 * refreshTimeSetting.getValue()))) { if (ServerUtils.isMultiplayer()) { - if (Objects.requireNonNull(mc.getCurrentServerEntry()).ping <= 1 && !pinging) { + if (Objects.requireNonNull(client.getCurrentServer()).ping <= 1 && !pinging) { Multithreading.runAsync(() -> { pinging = true; - ping = MCPing.pingModern().address(mc.getCurrentServerEntry().address).getSync().getPing(); + ping = MCPing.pingModern().address(client.getCurrentServer().ip).getSync().getPing(); pinging = false; }); } else { - ping = mc.getCurrentServerEntry().ping; + ping = Objects.requireNonNull(client.getCurrentServer()).ping; } - } else if (mc.isIntegratedServerRunning()) { + } else if (client.hasSingleplayerServer()) { ping = 0; } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/PitchDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/PitchDisplayMod.java index 30a4947..0b5a6cd 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/PitchDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/PitchDisplayMod.java @@ -3,7 +3,7 @@ import java.text.DecimalFormat; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; @@ -21,7 +21,7 @@ public PitchDisplayMod() { @Override public String getText() { - return "Pitch: " + df.format(mc.player.getPitch()); + return "Pitch: " + df.format(client.player.getViewXRot(0.0f)); } @Override diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/PlayTimeDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/PlayTimeDisplayMod.java index 7b79bb3..4eb1ae7 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/PlayTimeDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/PlayTimeDisplayMod.java @@ -2,7 +2,7 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/PlayerCounterMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/PlayerCounterMod.java index afa2204..d508d82 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/PlayerCounterMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/PlayerCounterMod.java @@ -1,10 +1,12 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; +import java.util.Objects; + public class PlayerCounterMod extends SimpleHUDMod { public PlayerCounterMod() { @@ -17,7 +19,8 @@ public PlayerCounterMod() { @Override public String getText() { - return "Player: " + mc.world.getPlayers().size(); + assert client.level != null; + return "Player: " + Objects.requireNonNull(client.level.getServer()).getPlayerCount(); } @Override diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/PotionHudMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/PotionHudMod.java index ee8b89b..ed1d66f 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/PotionHudMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/PotionHudMod.java @@ -2,7 +2,7 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.HUDMod; import cn.pupperclient.management.mod.settings.impl.BooleanSetting; import cn.pupperclient.management.mod.settings.impl.ComboSetting; @@ -10,15 +10,14 @@ import cn.pupperclient.skia.font.Fonts; import cn.pupperclient.skia.font.Icon; import cn.pupperclient.utils.misc.RomanConverter; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.effect.StatusEffect; -import net.minecraft.entity.effect.StatusEffectInstance; -import net.minecraft.registry.entry.RegistryEntry; - import java.awt.*; import java.util.*; import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import net.minecraft.client.Minecraft; +import net.minecraft.core.Holder; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; import static cn.pupperclient.management.mod.impl.hud.ArrayListMod.ICON_TEXT_SPACING; @@ -265,18 +264,18 @@ private void drawRoundedBackground(float x, float y, float width, int alpha) { private List getActivePotions() { List activePotions = new ArrayList<>(); - MinecraftClient client = MinecraftClient.getInstance(); + Minecraft client = Minecraft.getInstance(); if (client.player == null) return activePotions; // Get all active status effects - Collection effects = client.player.getStatusEffects(); + Collection effects = client.player.getActiveEffects(); - for (StatusEffectInstance effect : effects) { - RegistryEntry statusEffect = effect.getEffectType(); - String effectkey = statusEffect.value().getTranslationKey(); + for (MobEffectInstance effect : effects) { + Holder statusEffect = effect.getEffect(); + String effectkey = statusEffect.value().getDescriptionId(); String roman_converter = RomanConverter.intToRomanByPlace(effect.getAmplifier()); String amplifier = roman_converter.equals("0") ? " " : " " + roman_converter; - String effectName = statusEffect.value().getName().getString() + amplifier; + String effectName = statusEffect.value().getDisplayName().getString() + amplifier; String timeText = formatDuration(effect); // Calculate widths for layout @@ -295,8 +294,8 @@ private List getActivePotions() { return activePotions; } - private String formatDuration(StatusEffectInstance effect) { - if (effect.isInfinite()) { + private String formatDuration(MobEffectInstance effect) { + if (effect.isInfiniteDuration()) { return "inf"; } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/ProtocolVersionMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/ProtocolVersionMod.java index a6b58ba..2accf76 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/ProtocolVersionMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/ProtocolVersionMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; import com.viaversion.viafabricplus.ViaFabricPlus; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/ReachDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/ReachDisplayMod.java index 2a4b017..b8a22da 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/ReachDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/ReachDisplayMod.java @@ -1,18 +1,16 @@ package cn.pupperclient.management.mod.impl.hud; import java.text.DecimalFormat; - +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.event.server.impl.AttackEntityEvent; import cn.pupperclient.event.server.impl.DamageEntityEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; - public class ReachDisplayMod extends SimpleHUDMod { private DecimalFormat df = new DecimalFormat("0.##"); @@ -33,11 +31,14 @@ public ReachDisplayMod() { if (event.getEntityId() == possibleTarget) { - Entity entity = mc.world.getEntityById(event.getEntityId()); + assert client.level != null; + Entity entity = client.level.getEntity(event.getEntityId()); possibleTarget = -1; - distance = mc.player.getEyePos() - .distanceTo(closestPointToBox(mc.player.getEyePos(), entity.getBoundingBox())); + assert client.player != null; + assert entity != null; + distance = client.player.getEyePosition() + .distanceTo(closestPointToBox(client.player.getEyePosition(), entity.getBoundingBox())); hitTime = System.currentTimeMillis(); } }; @@ -46,8 +47,8 @@ public ReachDisplayMod() { possibleTarget = event.getEntityId(); }; - private Vec3d closestPointToBox(Vec3d start, Box box) { - return new Vec3d(coerceIn(start.x, box.minX, box.maxX), coerceIn(start.y, box.minY, box.maxY), + private Vec3 closestPointToBox(Vec3 start, AABB box) { + return new Vec3(coerceIn(start.x, box.minX, box.maxX), coerceIn(start.y, box.minY, box.maxY), coerceIn(start.z, box.minZ, box.maxZ)); } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/Scoreboard.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/Scoreboard.java index 9e9b1eb..9b0289f 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/Scoreboard.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/Scoreboard.java @@ -1,26 +1,24 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventListener; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleListHUDMod; import cn.pupperclient.skia.font.Icon; -import net.minecraft.client.MinecraftClient; -import net.minecraft.scoreboard.ScoreboardDisplaySlot; -import net.minecraft.scoreboard.ScoreboardEntry; -import net.minecraft.scoreboard.ScoreboardObjective; -import net.minecraft.scoreboard.Team; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; - import java.util.ArrayList; import java.util.Collection; import java.util.List; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.world.scores.DisplaySlot; +import net.minecraft.world.scores.Objective; +import net.minecraft.world.scores.PlayerScoreEntry; +import net.minecraft.world.scores.PlayerTeam; public class Scoreboard extends SimpleListHUDMod { private static Scoreboard instance; - private final MinecraftClient client = MinecraftClient.getInstance(); + private final Minecraft client = Minecraft.getInstance(); private List displayLines = new ArrayList<>(); public Scoreboard() { @@ -52,26 +50,26 @@ public void draw() { private void updateDisplayLines() { displayLines.clear(); - ScoreboardObjective scoreboardObjective = client.world.getScoreboard().getObjectiveForSlot(ScoreboardDisplaySlot.SIDEBAR); + Objective scoreboardObjective = client.level.getScoreboard().getDisplayObjective(DisplaySlot.SIDEBAR); if (scoreboardObjective == null) { return; } - net.minecraft.scoreboard.Scoreboard scoreboard = scoreboardObjective.getScoreboard(); - Collection scores = scoreboard.getScoreboardEntries(scoreboardObjective); + net.minecraft.world.scores.Scoreboard scoreboard = scoreboardObjective.getScoreboard(); + Collection scores = scoreboard.listPlayerScores(scoreboardObjective); if (scores.isEmpty()) { return; } // 添加标题 - 保留格式化字符 - Text titleText = scoreboardObjective.getDisplayName(); + Component titleText = scoreboardObjective.getDisplayName(); String formattedTitle = convertTextToFormattedString(titleText); displayLines.add(formattedTitle); // 过滤和排序 - List sortedScores = new ArrayList<>(); - for (ScoreboardEntry entry : scores) { - if (!entry.hidden()) { + List sortedScores = new ArrayList<>(); + for (PlayerScoreEntry entry : scores) { + if (!entry.isHidden()) { sortedScores.add(entry); } } @@ -80,19 +78,19 @@ private void updateDisplayLines() { // 添加积分项 int maxLines = Math.min(sortedScores.size(), 199); for (int i = 0; i < maxLines; i++) { - ScoreboardEntry entry = sortedScores.get(i); + PlayerScoreEntry entry = sortedScores.get(i); String line = getFormattedScoreText(entry, scoreboard); displayLines.add(line); } } - private String getFormattedScoreText(ScoreboardEntry entry, net.minecraft.scoreboard.Scoreboard scoreboard) { + private String getFormattedScoreText(PlayerScoreEntry entry, net.minecraft.world.scores.Scoreboard scoreboard) { String playerName = entry.owner(); - Team team = scoreboard.getScoreHolderTeam(playerName); + PlayerTeam team = scoreboard.getPlayersTeam(playerName); String displayName; if (team != null) { - Text formattedName = entry.name(); + Component formattedName = entry.ownerName(); // 使用新的格式化方法 displayName = convertTextToFormattedString(formattedName); } else { @@ -106,7 +104,7 @@ private String getFormattedScoreText(ScoreboardEntry entry, net.minecraft.scoreb * 将 Minecraft Text 对象转换为包含格式化字符的字符串 * 保留颜色代码和格式化信息 */ - private String convertTextToFormattedString(Text text) { + private String convertTextToFormattedString(Component text) { StringBuilder result = new StringBuilder(); convertTextRecursive(text, result); return result.toString(); @@ -115,14 +113,14 @@ private String convertTextToFormattedString(Text text) { /** * 递归处理 Text 对象及其子组件 */ - private void convertTextRecursive(Text text, StringBuilder result) { + private void convertTextRecursive(Component text, StringBuilder result) { // 处理当前文本的样式 if (text.getStyle() != null) { // 添加颜色代码 if (text.getStyle().getColor() != null) { - Formatting formatting = Formatting.byName(text.getStyle().getColor().getName()); + ChatFormatting formatting = ChatFormatting.getByName(text.getStyle().getColor().serialize()); if (formatting != null && formatting.isColor()) { - result.append("§").append(formatting.getCode()); + result.append("§").append(formatting.getChar()); } } @@ -151,7 +149,7 @@ private void convertTextRecursive(Text text, StringBuilder result) { } // 递归处理子组件 - for (Text sibling : text.getSiblings()) { + for (Component sibling : text.getSiblings()) { convertTextRecursive(sibling, result); } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/ServerIPDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/ServerIPDisplayMod.java index 5d59ee3..33dcef7 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/ServerIPDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/ServerIPDisplayMod.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; import cn.pupperclient.utils.server.ServerUtils; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/SpeedometerMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/SpeedometerMod.java index 3ef0bf5..f63f4ce 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/SpeedometerMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/SpeedometerMod.java @@ -1,15 +1,13 @@ package cn.pupperclient.management.mod.impl.hud; import java.text.DecimalFormat; - +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.Vec3d; - public class SpeedometerMod extends SimpleHUDMod { private DecimalFormat speedFormat = new DecimalFormat("0.00"); @@ -27,13 +25,13 @@ public String getText() { String suffix = " m/s"; - if (mc.player != null) { + if (client.player != null) { - Entity entity = mc.player.getVehicle() == null ? mc.player : mc.player.getVehicle(); - Vec3d vec = entity.getMovement(); + Entity entity = client.player.getVehicle() == null ? client.player : client.player.getVehicle(); + Vec3 vec = entity.getKnownMovement(); - if (entity.isOnGround() && vec.y < 0) { - vec = new Vec3d(vec.x, 0, vec.z); + if (entity.onGround() && vec.y < 0) { + vec = new Vec3(vec.x, 0, vec.z); } return speedFormat.format(vec.length() * 20) + suffix; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/StopwatchMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/StopwatchMod.java index 762618f..37dad33 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/StopwatchMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/StopwatchMod.java @@ -2,17 +2,17 @@ import java.text.DecimalFormat; +import net.minecraft.client.input.KeyEvent; import org.lwjgl.glfw.GLFW; import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.ClientTickEvent; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.management.mod.settings.impl.KeybindSetting; import cn.pupperclient.skia.font.Icon; import cn.pupperclient.utils.time.TimerUtils; - -import net.minecraft.client.util.InputUtil; +import com.mojang.blaze3d.platform.InputConstants; public class StopwatchMod extends SimpleHUDMod { @@ -22,7 +22,7 @@ public class StopwatchMod extends SimpleHUDMod { private DecimalFormat timeFormat = new DecimalFormat("0.00"); private KeybindSetting keybindSetting = new KeybindSetting("setting.keybind", "setting.keybind.description", - Icon.KEYBOARD, this, InputUtil.fromKeyCode(GLFW.GLFW_KEY_P, 0)); + Icon.KEYBOARD, this, InputConstants.getKey(new KeyEvent(GLFW.GLFW_KEY_P, 0, 0))); public StopwatchMod() { super("mod.stopwatch.name", "mod.stopwatch.description", Icon.TIMER); diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/TargetHUDMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/TargetHUDMod.java index a038a02..10326bd 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/TargetHUDMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/TargetHUDMod.java @@ -7,7 +7,7 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.ClientTickEvent; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.gui.edithud.api.HUDCore; import cn.pupperclient.management.color.api.ColorPalette; import cn.pupperclient.management.mod.api.hud.HUDMod; @@ -20,16 +20,16 @@ import cn.pupperclient.utils.minecraft.player.SkinUtils; import net.fabricmc.fabric.api.event.player.AttackEntityCallback; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.ActionResult; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; public class TargetHUDMod extends HUDMod { private static TargetHUDMod instance; - private PlayerEntity targetPlayer; + private Player targetPlayer; private long lastAttackTime = 0; private static final long DISPLAY_DURATION = 10000; @@ -72,14 +72,14 @@ public void onDisable() { private void registerFabricCallbacks() { AttackEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> { - if (world.isClient && player instanceof ClientPlayerEntity && entity instanceof PlayerEntity newTarget) { + if (world.isClientSide() && player instanceof LocalPlayer && entity instanceof Player newTarget) { updateTarget(newTarget); } - return ActionResult.PASS; + return InteractionResult.PASS; }); } - private void updateTarget(PlayerEntity newTarget) { + private void updateTarget(Player newTarget) { if (targetPlayer == null || !targetPlayer.equals(newTarget)) { targetPlayer = newTarget; lastAttackTime = System.currentTimeMillis(); @@ -139,10 +139,10 @@ private boolean shouldShowTarget() { private void drawTargetInfo(float width, float height) { boolean isEditing = HUDCore.isEditing; - PlayerEntity displayPlayer; + Player displayPlayer; if (isEditing) { - displayPlayer = MinecraftClient.getInstance().player; + displayPlayer = Minecraft.getInstance().player; } else { displayPlayer = targetPlayer; } @@ -152,8 +152,8 @@ private void drawTargetInfo(float width, float height) { } if (!isEditing) { - MinecraftClient client = MinecraftClient.getInstance(); - if (client.world == null || client.world.getEntityById(displayPlayer.getId()) == null) { + Minecraft client = Minecraft.getInstance(); + if (client.level == null || client.level.getEntity(displayPlayer.getId()) == null) { targetPlayer = null; return; } @@ -260,7 +260,7 @@ private Color blendColors(Color color1, Color color2, float factor) { return new Color(red, green, blue, alpha); } - private void drawPlayerAvatar(PlayerEntity player, float x, float y, float size) { + private void drawPlayerAvatar(Player player, float x, float y, float size) { Skia.save(); try { @@ -283,10 +283,10 @@ private void drawPlayerAvatar(PlayerEntity player, float x, float y, float size) } } - private File getSkinFile(PlayerEntity player) { - if (player instanceof AbstractClientPlayerEntity clientPlayer) { - if (clientPlayer.getSkinTextures() != null) { - File skinFile = SkinUtils.getSkin(clientPlayer.getSkinTextures().texture()); + private File getSkinFile(Player player) { + if (player instanceof AbstractClientPlayer clientPlayer) { + if (clientPlayer.getSkin() != null) { + File skinFile = SkinUtils.getSkin(clientPlayer.getSkin().body().texturePath()); if (skinFile.exists()) { return skinFile; } @@ -295,7 +295,7 @@ private File getSkinFile(PlayerEntity player) { return null; } - private float getPlayerHealth(PlayerEntity player) { + private float getPlayerHealth(Player player) { if (player == null) { return 20.0f; } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/Test.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/Test.java index 6fc3d3c..a9f671d 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/Test.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/Test.java @@ -1,7 +1,7 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventListener; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleListHUDMod; import java.util.List; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/WatermarkMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/WatermarkMod.java index cecd4eb..56c1088 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/WatermarkMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/WatermarkMod.java @@ -7,7 +7,7 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.PupperLogger; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.color.api.ColorPalette; import cn.pupperclient.management.mod.api.hud.HUDMod; import cn.pupperclient.management.mod.settings.impl.BooleanSetting; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/WeatherDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/WeatherDisplayMod.java index c156c26..95ff2e1 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/WeatherDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/WeatherDisplayMod.java @@ -1,15 +1,14 @@ package cn.pupperclient.management.mod.impl.hud; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; - -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.biome.Biome; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.world.level.biome.Biome; public class WeatherDisplayMod extends SimpleHUDMod { @@ -25,17 +24,17 @@ public WeatherDisplayMod() { public String getText() { String prefix = "Weather: "; - ClientWorld world = mc.world; - ClientPlayerEntity player = mc.player; - BlockPos playerPos = player.getBlockPos(); - RegistryEntry biomeEntry = world.getBiome(playerPos); + ClientLevel world = client.level; + LocalPlayer player = client.player; + BlockPos playerPos = player.blockPosition(); + Holder biomeEntry = world.getBiome(playerPos); if (world.isThundering()) { return prefix + "Thundering"; } if (world.isRaining()) { - if (biomeEntry.value().getPrecipitation(playerPos, world.getSeaLevel()).equals(Biome.Precipitation.SNOW)) { + if (biomeEntry.value().getPrecipitationAt(playerPos, world.getSeaLevel()).equals(Biome.Precipitation.SNOW)) { return prefix + "Snowing"; } else { return prefix + "Raining"; @@ -47,11 +46,10 @@ public String getText() { @Override public String getIcon() { - - ClientWorld world = mc.world; - ClientPlayerEntity player = mc.player; - BlockPos playerPos = player.getBlockPos(); - RegistryEntry biomeEntry = world.getBiome(playerPos); + ClientLevel world = client.level; + LocalPlayer player = client.player; + BlockPos playerPos = player.blockPosition(); + Holder biomeEntry = world.getBiome(playerPos); String iconFont = Icon.SUNNY; @@ -60,7 +58,7 @@ public String getIcon() { } if (world.isRaining()) { - if (biomeEntry.value().getPrecipitation(playerPos, world.getSeaLevel()).equals(Biome.Precipitation.SNOW)) { + if (biomeEntry.value().getPrecipitationAt(playerPos, world.getSeaLevel()).equals(Biome.Precipitation.SNOW)) { iconFont = Icon.WEATHER_SNOWY; } else { iconFont = Icon.RAINY; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/hud/YawDisplayMod.java b/src/main/java/cn/pupperclient/management/mod/impl/hud/YawDisplayMod.java index 0f46916..65d9f01 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/hud/YawDisplayMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/hud/YawDisplayMod.java @@ -3,7 +3,7 @@ import java.text.DecimalFormat; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.api.hud.SimpleHUDMod; import cn.pupperclient.skia.font.Icon; @@ -21,7 +21,7 @@ public YawDisplayMod() { @Override public String getText() { - return "Yaw: " + df.format(Math.abs(mc.player.getYaw() % 90)); + return "Yaw: " + df.format(Math.abs(client.player.getViewYRot(0.0f) % 90)); } @Override diff --git a/src/main/java/cn/pupperclient/management/mod/impl/misc/HypixelMod.java b/src/main/java/cn/pupperclient/management/mod/impl/misc/HypixelMod.java index 6b980f9..f5287a0 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/misc/HypixelMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/misc/HypixelMod.java @@ -27,9 +27,9 @@ public HypixelMod() { } public final EventBus.EventListener onClientTick = event -> { - if (autoTipSetting.isEnabled() && mc.player != null && ServerUtils.isJoin(Server.HYPIXEL)) { + if (autoTipSetting.isEnabled() && client.player != null && ServerUtils.isJoin(Server.HYPIXEL)) { if (tipTimer.delay(1200000)) { - mc.player.networkHandler.sendChatCommand("tip all"); + client.player.connection.sendCommand("tip all"); tipTimer.reset(); } } else { diff --git a/src/main/java/cn/pupperclient/management/mod/impl/misc/IRCChatMod.java b/src/main/java/cn/pupperclient/management/mod/impl/misc/IRCChatMod.java index 8f79c46..5874e04 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/misc/IRCChatMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/misc/IRCChatMod.java @@ -11,10 +11,10 @@ import cn.pupperclient.management.mod.settings.impl.NumberSetting; import cn.pupperclient.management.mod.settings.impl.StringSetting; import cn.pupperclient.skia.font.Icon; +import cn.pupperclient.utils.chat.ChatUtils; import cn.pupperclient.utils.minecraft.interfaces.IMinecraft; -import net.minecraft.text.Text; - import java.io.IOException; +import net.minecraft.network.chat.Component; public class IRCChatMod extends Mod implements IMinecraft, IRCHandler { @@ -69,9 +69,9 @@ public void onDisable() { // IRCHandler implementation @Override public void onMessage(String sender, String message) throws IOException { - if (showMessagesSetting.isEnabled() && mc.player != null) { + if (showMessagesSetting.isEnabled() && client.player != null) { String formattedMessage = String.format("§9[IRC] §b%s§f: %s", sender, message); - mc.player.sendMessage(Text.of(formattedMessage), false); + ChatUtils.addChatMessage(Component.nullToEmpty(formattedMessage)); } } @@ -81,8 +81,8 @@ public void onDisconnected(String message) { lastError = message; PupperClient.LOGGER.warn("IRC disconnected: {}", message); - if (mc.player != null) { - mc.player.sendMessage(Text.of("§cIRC disconnected: " + message), false); + if (client.player != null) { + ChatUtils.addChatMessage(Component.nullToEmpty("§cIRC disconnected: " + message)); } // Schedule reconnect if auto-connect is enabled @@ -97,16 +97,16 @@ public void onConnected() { lastError = ""; PupperClient.LOGGER.info("IRC connected successfully"); - if (mc.player != null) { - mc.player.sendMessage(Text.of("§aConnected to IRC server!"), false); + if (client.player != null) { + ChatUtils.addChatMessage(Component.nullToEmpty("§aConnected to IRC server!")); } } @Override public String getInGameUsername() { // Use Minecraft username if available, otherwise use setting - if (mc.player != null) { - return mc.player.getGameProfile().getName(); + if (client.player != null) { + return client.player.getGameProfile().name(); } return usernameSetting.getValue(); } @@ -124,7 +124,7 @@ public String getInGameUsername() { } // Update in-game name periodically if connected - if (isConnected && transport != null && mc.player != null) { + if (isConnected && transport != null && client.player != null) { // This will be handled by the transport's scheduled task } }; @@ -153,8 +153,8 @@ public void connectToIRC() { lastError = e.getMessage(); PupperClient.LOGGER.error("Failed to create IRC transport", e); - if (mc.player != null) { - mc.player.sendMessage(Text.of("§cFailed to connect to IRC: " + e.getMessage()), false); + if (client.player != null) { + ChatUtils.addChatMessage(Component.nullToEmpty("§cFailed to connect to IRC: " + e.getMessage())); } transport = null; @@ -210,8 +210,8 @@ public String getServerInfo() { } private void sendChatMessage(String message) { - if (mc.player != null) { - mc.player.sendMessage(Text.of(message), false); + if (client.player != null) { + ChatUtils.addChatMessage(Component.nullToEmpty(message)); } } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/player/AutoGGMod.java b/src/main/java/cn/pupperclient/management/mod/impl/player/AutoGGMod.java index cb02e6d..0b3e961 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/player/AutoGGMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/player/AutoGGMod.java @@ -64,12 +64,12 @@ private void processChat(List options, String message) { private void sendMessage(boolean hypixel) { Multithreading.schedule(() -> { if (hypixel) { - if (mc.player != null) { - mc.player.networkHandler.sendChatCommand("achat " + messageSetting.getValue()); + if (client.player != null) { + client.player.connection.sendCommand("achat " + messageSetting.getValue()); } } else { - if (mc.player != null) { - mc.player.networkHandler.sendChatMessage(messageSetting.getValue()); + if (client.player != null) { + client.player.connection.sendChat(messageSetting.getValue()); } } }, (long) delaySetting.getValue(), TimeUnit.SECONDS); diff --git a/src/main/java/cn/pupperclient/management/mod/impl/player/AutoTextMod.java b/src/main/java/cn/pupperclient/management/mod/impl/player/AutoTextMod.java index dd93e02..7066382 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/player/AutoTextMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/player/AutoTextMod.java @@ -7,14 +7,14 @@ import cn.pupperclient.management.mod.settings.impl.KeybindSetting; import cn.pupperclient.management.mod.settings.impl.StringSetting; import cn.pupperclient.skia.font.Icon; -import net.minecraft.client.util.InputUtil; +import com.mojang.blaze3d.platform.InputConstants; public class AutoTextMod extends Mod { - private KeybindSetting text1KeybindSetting = new KeybindSetting("setting.text1key", "setting.text1key.description", Icon.KEYBOARD, this, InputUtil.UNKNOWN_KEY); + private KeybindSetting text1KeybindSetting = new KeybindSetting("setting.text1key", "setting.text1key.description", Icon.KEYBOARD, this, InputConstants.UNKNOWN); private StringSetting text1Setting = new StringSetting("setting.text1", "setting.text1.description", Icon.TEXT_FORMAT, this, ""); - private KeybindSetting text2KeybindSetting = new KeybindSetting("setting.text2key", "setting.text2key.description", Icon.KEYBOARD, this, InputUtil.UNKNOWN_KEY); + private KeybindSetting text2KeybindSetting = new KeybindSetting("setting.text2key", "setting.text2key.description", Icon.KEYBOARD, this, InputConstants.UNKNOWN); private StringSetting text2Setting = new StringSetting("setting.text2", "setting.text2.description", Icon.TEXT_FORMAT, this, ""); - private KeybindSetting text3KeybindSetting = new KeybindSetting("setting.text3key", "setting.text3key.description", Icon.KEYBOARD, this, InputUtil.UNKNOWN_KEY); + private KeybindSetting text3KeybindSetting = new KeybindSetting("setting.text3key", "setting.text3key.description", Icon.KEYBOARD, this, InputConstants.UNKNOWN); private StringSetting text3Setting = new StringSetting("setting.text3", "setting.text3.description", Icon.TEXT_FORMAT, this, ""); @Override @@ -32,20 +32,20 @@ public AutoTextMod() { } public final EventBus.EventListener onClientTick = event -> { - if (mc.player != null) { + if (client.player != null) { return; } if(text1KeybindSetting.isPressed()) { - mc.player.networkHandler.sendChatMessage(text1Setting.getValue()); + client.player.connection.sendChat(text1Setting.getValue()); } if(text2KeybindSetting.isPressed()) { - mc.player.networkHandler.sendChatMessage(text2Setting.getValue()); + client.player.connection.sendChat(text2Setting.getValue()); } if(text3KeybindSetting.isPressed()) { - mc.player.networkHandler.sendChatMessage(text3Setting.getValue()); + client.player.connection.sendChat(text3Setting.getValue()); } }; } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/player/FreelookMod.java b/src/main/java/cn/pupperclient/management/mod/impl/player/FreelookMod.java index 9805c7c..49418b6 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/player/FreelookMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/player/FreelookMod.java @@ -1,7 +1,8 @@ package cn.pupperclient.management.mod.impl.player; import java.util.Arrays; - +import net.minecraft.client.CameraType; +import net.minecraft.client.input.KeyEvent; import org.lwjgl.glfw.GLFW; import cn.pupperclient.event.EventBus; @@ -12,23 +13,21 @@ import cn.pupperclient.management.mod.settings.impl.ComboSetting; import cn.pupperclient.management.mod.settings.impl.KeybindSetting; import cn.pupperclient.skia.font.Icon; - -import net.minecraft.client.option.Perspective; -import net.minecraft.client.util.InputUtil; +import com.mojang.blaze3d.platform.InputConstants; public class FreelookMod extends Mod { private static FreelookMod instance; private boolean active; private boolean toggled; - private Perspective prevPerspective; + private CameraType prevPerspective; private ComboSetting perspectiveSetting = new ComboSetting("setting.perspective", "setting.perspective.description", Icon.CAMERASWITCH, this, Arrays.asList("setting.front", "setting.behind"), "setting.behind"); private BooleanSetting toggleSetting = new BooleanSetting("setting.toggle", "setting.toggle.description", Icon.SWITCH, this, false); private KeybindSetting keybindSetting = new KeybindSetting("setting.keybind", "setting.keybind.description", - Icon.KEYBOARD, this, InputUtil.fromKeyCode(GLFW.GLFW_KEY_B, 0)); + Icon.KEYBOARD, this, InputConstants.getKey(new KeyEvent(GLFW.GLFW_KEY_B, 0, 0))); public FreelookMod() { super("mod.freelook.name", "mod.freelook.description", Icon._360, ModCategory.PLAYER); @@ -68,17 +67,17 @@ public FreelookMod() { private void start() { String option = perspectiveSetting.getOption(); - Perspective perspective = option.equals("setting.front") ? Perspective.THIRD_PERSON_FRONT - : Perspective.THIRD_PERSON_BACK; + CameraType perspective = option.equals("setting.front") ? CameraType.THIRD_PERSON_FRONT + : CameraType.THIRD_PERSON_BACK; active = true; - prevPerspective = mc.options.getPerspective(); - mc.options.setPerspective(perspective); + prevPerspective = client.options.getCameraType(); + client.options.setCameraType(perspective); } private void stop() { active = false; - mc.options.setPerspective(prevPerspective); + client.options.setCameraType(prevPerspective); } public static FreelookMod getInstance() { diff --git a/src/main/java/cn/pupperclient/management/mod/impl/player/Sprint.java b/src/main/java/cn/pupperclient/management/mod/impl/player/Sprint.java index 88ee19e..94bbde2 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/player/Sprint.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/player/Sprint.java @@ -23,6 +23,6 @@ public void onDisable() { @EventListener public void onTick(ClientTickEvent event) { - mc.options.sprintKey.setPressed(true); + client.options.keySprint.setDown(true); } } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/player/TaplookMod.java b/src/main/java/cn/pupperclient/management/mod/impl/player/TaplookMod.java index 1581b09..209fe71 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/player/TaplookMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/player/TaplookMod.java @@ -1,7 +1,8 @@ package cn.pupperclient.management.mod.impl.player; import java.util.Arrays; - +import net.minecraft.client.CameraType; +import net.minecraft.client.input.KeyEvent; import org.lwjgl.glfw.GLFW; import cn.pupperclient.event.EventBus; @@ -12,14 +13,12 @@ import cn.pupperclient.management.mod.settings.impl.ComboSetting; import cn.pupperclient.management.mod.settings.impl.KeybindSetting; import cn.pupperclient.skia.font.Icon; - -import net.minecraft.client.option.Perspective; -import net.minecraft.client.util.InputUtil; +import com.mojang.blaze3d.platform.InputConstants; public class TaplookMod extends Mod { private boolean active; - private Perspective prevPerspective; + private CameraType prevPerspective; private boolean toggled; private ComboSetting perspectiveSetting = new ComboSetting("setting.perspective", "setting.perspective.description", @@ -27,7 +26,7 @@ public class TaplookMod extends Mod { private BooleanSetting toggleSetting = new BooleanSetting("setting.toggle", "setting.toggle.description", Icon.SWITCH, this, false); private KeybindSetting keybindSetting = new KeybindSetting("setting.keybind", "setting.keybind.description", - Icon.KEYBOARD, this, InputUtil.fromKeyCode(GLFW.GLFW_KEY_V, 0)); + Icon.KEYBOARD, this, InputConstants.getKey(new KeyEvent(GLFW.GLFW_KEY_V, 0, 0))); public TaplookMod() { super("mod.taplook.name", "mod.taplook.description", Icon.TOUCH_APP, ModCategory.PLAYER); @@ -64,16 +63,16 @@ public TaplookMod() { private void start() { String option = perspectiveSetting.getOption(); - Perspective perspective = option.equals("setting.front") ? Perspective.THIRD_PERSON_FRONT - : Perspective.THIRD_PERSON_BACK; + CameraType perspective = option.equals("setting.front") ? CameraType.THIRD_PERSON_FRONT + : CameraType.THIRD_PERSON_BACK; active = true; - prevPerspective = mc.options.getPerspective(); - mc.options.setPerspective(perspective); + prevPerspective = client.options.getCameraType(); + client.options.setCameraType(perspective); } private void stop() { active = false; - mc.options.setPerspective(prevPerspective); + client.options.setCameraType(prevPerspective); } } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/player/ZoomMod.java b/src/main/java/cn/pupperclient/management/mod/impl/player/ZoomMod.java index f6be745..328a271 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/player/ZoomMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/player/ZoomMod.java @@ -1,6 +1,7 @@ package cn.pupperclient.management.mod.impl.player; +import net.minecraft.client.input.KeyEvent; import org.lwjgl.glfw.GLFW; import cn.pupperclient.animation.SimpleAnimation; @@ -13,8 +14,7 @@ import cn.pupperclient.management.mod.settings.impl.KeybindSetting; import cn.pupperclient.management.mod.settings.impl.NumberSetting; import cn.pupperclient.skia.font.Icon; - -import net.minecraft.client.util.InputUtil; +import com.mojang.blaze3d.platform.InputConstants; public class ZoomMod extends Mod { @@ -38,7 +38,7 @@ public class ZoomMod extends Mod { private BooleanSetting smoothCameraSetting = new BooleanSetting("setting.smoothcamera", "setting.smoothcamera.description", Icon.MOTION_BLUR, this, true); private KeybindSetting keybindSetting = new KeybindSetting("setting.keybind", "setting.keybind.description", - Icon.KEYBOARD, this, InputUtil.fromKeyCode(GLFW.GLFW_KEY_C, 0)); + Icon.KEYBOARD, this, InputConstants.getKey(new KeyEvent(GLFW.GLFW_KEY_C, 0, 0))); public ZoomMod() { super("mod.zoom.name", "mod.zoom.description", Icon.ZOOM_IN, ModCategory.PLAYER); @@ -51,13 +51,13 @@ public ZoomMod() { if (!active) { active = true; resetFactor(); - wasSmooth = mc.options.smoothCameraEnabled; - mc.options.smoothCameraEnabled = smoothCameraSetting.isEnabled(); + wasSmooth = client.options.smoothCamera; + client.options.smoothCamera = smoothCameraSetting.isEnabled(); } } else if (active) { active = false; setFactor(1); - mc.options.smoothCameraEnabled = wasSmooth; + client.options.smoothCamera = wasSmooth; } }; @@ -66,11 +66,11 @@ public ZoomMod() { event.setCancelled(true); if (event.getAmount() < 0) { if (currentFactor < 0.98) { - currentFactor += 0.03; + currentFactor += 0.03F; } } else if (event.getAmount() > 0) { if (currentFactor > 0.06) { - currentFactor -= 0.03; + currentFactor -= 0.03F; } } } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/render/BloodParticleMod.java b/src/main/java/cn/pupperclient/management/mod/impl/render/BloodParticleMod.java index 6872ab1..8b436ab 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/render/BloodParticleMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/render/BloodParticleMod.java @@ -7,16 +7,15 @@ import cn.pupperclient.management.mod.settings.impl.BooleanSetting; import cn.pupperclient.management.mod.settings.impl.NumberSetting; import cn.pupperclient.skia.font.Icon; - -import net.minecraft.block.Blocks; -import net.minecraft.client.sound.PositionedSoundInstance; -import net.minecraft.client.sound.SoundInstance; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.particle.BlockStateParticleEffect; -import net.minecraft.particle.ParticleTypes; -import net.minecraft.sound.SoundCategory; -import net.minecraft.sound.SoundEvents; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.client.resources.sounds.SoundInstance; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.block.Blocks; public class BloodParticleMod extends Mod { @@ -32,21 +31,21 @@ public BloodParticleMod() { public final EventBus.EventListener onAttackEntity = event -> { Entity target = null; - if (mc.world != null) { - target = mc.world.getEntityById(event.getEntityId()); + if (client.level != null) { + target = client.level.getEntity(event.getEntityId()); } if (target instanceof LivingEntity) { for (int i = 0; i < multiplierSetting.getValue(); i++) { - mc.particleManager.addEmitter(target, - new BlockStateParticleEffect(ParticleTypes.BLOCK, Blocks.REDSTONE_BLOCK.getDefaultState())); + client.particleEngine.createTrackingEmitter(target, + new BlockParticleOption(ParticleTypes.BLOCK, Blocks.REDSTONE_BLOCK.defaultBlockState())); } } if (soundSetting.isEnabled() && target != null) { - mc.getSoundManager() - .play(new PositionedSoundInstance(SoundEvents.BLOCK_STONE_BREAK.id(), SoundCategory.BLOCKS, 4.0F, - 1.2F, SoundInstance.createRandom(), false, 0, SoundInstance.AttenuationType.LINEAR, + client.getSoundManager() + .play(new SimpleSoundInstance(SoundEvents.STONE_BREAK.location(), SoundSource.BLOCKS, 4.0F, + 1.2F, SoundInstance.createUnseededRandom(), false, 0, SoundInstance.Attenuation.LINEAR, target.getX(), target.getY(), target.getZ(), false)); } }; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/render/ClickEffectMod.java b/src/main/java/cn/pupperclient/management/mod/impl/render/ClickEffectMod.java index c874ac5..419b6d5 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/render/ClickEffectMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/render/ClickEffectMod.java @@ -2,7 +2,7 @@ import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.MouseClickEvent; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.Mod; import cn.pupperclient.management.mod.ModCategory; import cn.pupperclient.management.mod.settings.impl.BooleanSetting; @@ -10,10 +10,7 @@ import cn.pupperclient.management.mod.settings.impl.NumberSetting; import cn.pupperclient.skia.font.Icon; import cn.pupperclient.utils.render.RippleEffect; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; -import net.minecraft.client.util.Window; +import com.mojang.blaze3d.platform.Window; import io.github.humbleui.skija.Canvas; import io.github.humbleui.skija.Paint; import io.github.humbleui.skija.Shader; @@ -24,6 +21,9 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; public class ClickEffectMod extends Mod { @@ -73,9 +73,9 @@ public void onEnable() { super.onEnable(); // 注册事件监听器 EventBus.getInstance().register(this); - Window window = MinecraftClient.getInstance().getWindow(); - windowWidth = window.getScaledWidth(); - windowHeight = window.getScaledHeight(); + Window window = Minecraft.getInstance().getWindow(); + windowWidth = window.getGuiScaledWidth(); + windowHeight = window.getGuiScaledHeight(); } @Override @@ -86,8 +86,8 @@ public void onDisable() { } public final EventBus.EventListener onMouseClick = event -> { - if ((mc.currentScreen instanceof TitleScreen - || mc.currentScreen instanceof MultiplayerScreen) + if ((client.screen instanceof TitleScreen + || client.screen instanceof JoinMultiplayerScreen) && (event.getButton() == GLFW.GLFW_MOUSE_BUTTON_LEFT || event.getButton() == GLFW.GLFW_MOUSE_BUTTON_RIGHT) ) { @@ -101,9 +101,9 @@ public void onDisable() { }; public final EventBus.EventListener onRenderSkia = event -> { - Window window = MinecraftClient.getInstance().getWindow(); - windowWidth = window.getScaledWidth(); - windowHeight = window.getScaledHeight(); + Window window = Minecraft.getInstance().getWindow(); + windowWidth = window.getGuiScaledWidth(); + windowHeight = window.getGuiScaledHeight(); Iterator iterator = ripples.iterator(); while (iterator.hasNext()) { @@ -118,8 +118,8 @@ public void onDisable() { }; private void renderRipple(Canvas canvas, RippleEffect ripple, Color baseColor) { - Window window = MinecraftClient.getInstance().getWindow(); - float windowHeight = window.getScaledHeight(); + Window window = Minecraft.getInstance().getWindow(); + float windowHeight = window.getGuiScaledHeight(); float flippedY = windowHeight - ripple.getY(); diff --git a/src/main/java/cn/pupperclient/management/mod/impl/render/MusicWaveformMod.java b/src/main/java/cn/pupperclient/management/mod/impl/render/MusicWaveformMod.java index 4f364d7..e151ea0 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/render/MusicWaveformMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/render/MusicWaveformMod.java @@ -2,7 +2,7 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; +import cn.pupperclient.event.skia.RenderSkiaEvent; import cn.pupperclient.management.mod.Mod; import cn.pupperclient.management.mod.ModCategory; import cn.pupperclient.management.music.Music; @@ -30,8 +30,8 @@ public MusicWaveformMod() { for (int i = 0; i < MusicPlayer.SPECTRUM_BANDS; i++) { MusicPlayer.ANIMATIONS[i].onTick(MusicPlayer.VISUALIZER[i], 10); - Skia.drawRect(offsetX, mc.getWindow().getScaledHeight() + MusicPlayer.ANIMATIONS[i].getValue(), 10, - mc.getWindow().getScaledHeight(), ColorUtils.applyAlpha(m.getColor(), 80)); + Skia.drawRect(offsetX, client.getWindow().getGuiScaledHeight() + MusicPlayer.ANIMATIONS[i].getValue(), 10, + client.getWindow().getGuiScaledHeight(), ColorUtils.applyAlpha(m.getColor(), 80)); offsetX += 10; } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/render/ParticlesMod.java b/src/main/java/cn/pupperclient/management/mod/impl/render/ParticlesMod.java index 25cc181..b0718c4 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/render/ParticlesMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/render/ParticlesMod.java @@ -7,15 +7,16 @@ import cn.pupperclient.management.mod.settings.impl.BooleanSetting; import cn.pupperclient.management.mod.settings.impl.NumberSetting; import cn.pupperclient.skia.font.Icon; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.enchantment.Enchantments; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.effect.StatusEffects; -import net.minecraft.particle.ParticleTypes; -import net.minecraft.registry.RegistryKeys; +import java.util.Objects; public class ParticlesMod extends Mod { @@ -40,27 +41,29 @@ public ParticlesMod() { int sharpnessAmount = (int) sharpnessAmountSetting.getValue(); int criticalsAmount = (int) criticalsAmountSetting.getValue(); - Entity target = mc.world.getEntityById(event.getEntityId()); - ClientPlayerEntity player = mc.player; + Entity target = client.level.getEntity(event.getEntityId()); + LocalPlayer player = client.player; - boolean critical = criticalsSetting.isEnabled() && player.getAttackCooldownProgress(0.5F) > 0.9F - && !player.isOnGround() && !player.isClimbing() && !player.isTouchingWater() - && !player.hasStatusEffect(StatusEffects.BLINDNESS) && !player.hasVehicle() + boolean critical = criticalsSetting.isEnabled() && player.getAttackStrengthScale(0.5F) > 0.9F + && !player.onGround() && !player.onClimbable() && !player.isInWater() + && !player.hasEffect(MobEffects.BLINDNESS) && !player.isPassenger() && target instanceof LivingEntity && !player.isSprinting(); boolean alwaysSharpness = alwaysSharpnessSetting.isEnabled(); - boolean sharpness = sharpnessSetting.isEnabled() && EnchantmentHelper.getLevel(mc.world.getRegistryManager() - .getOrThrow(RegistryKeys.ENCHANTMENT).getOrThrow(Enchantments.SHARPNESS), player.getWeaponStack()) > 0; + boolean sharpness = sharpnessSetting.isEnabled() && EnchantmentHelper.getItemEnchantmentLevel(client.level.registryAccess() + .lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(Enchantments.SHARPNESS), Objects.requireNonNull(player).getWeaponItem()) > 0; boolean alwaysCriticals = alwaysCriticalsSetting.isEnabled(); if (critical || alwaysCriticals) { for (int i = 0; i < criticalsAmount - 1; i++) { - mc.particleManager.addEmitter(target, ParticleTypes.CRIT); + assert target != null; + client.particleEngine.createTrackingEmitter(target, ParticleTypes.CRIT); } } if (alwaysSharpness || sharpness) { for (int i = 0; i < sharpnessAmount - 1; i++) { - mc.particleManager.addEmitter(target, ParticleTypes.ENCHANTED_HIT); + assert target != null; + client.particleEngine.createTrackingEmitter(target, ParticleTypes.ENCHANTED_HIT); } } }; diff --git a/src/main/java/cn/pupperclient/management/mod/impl/render/ProjectileTrailMod.java b/src/main/java/cn/pupperclient/management/mod/impl/render/ProjectileTrailMod.java index 670bd13..daf4bec 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/render/ProjectileTrailMod.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/render/ProjectileTrailMod.java @@ -2,7 +2,11 @@ import java.util.Arrays; import java.util.Objects; - +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.phys.AABB; import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.ClientTickEvent; import cn.pupperclient.management.mod.Mod; @@ -10,12 +14,6 @@ import cn.pupperclient.management.mod.settings.impl.ComboSetting; import cn.pupperclient.skia.font.Icon; -import net.minecraft.entity.projectile.ProjectileEntity; -import net.minecraft.particle.ParticleEffect; -import net.minecraft.particle.ParticleType; -import net.minecraft.particle.ParticleTypes; -import net.minecraft.util.math.Box; - public class ProjectileTrailMod extends Mod { private ComboSetting effectSetting = new ComboSetting("setting.effect", "setting.effect.description", @@ -30,24 +28,24 @@ public ProjectileTrailMod() { public final EventBus.EventListener onClientTick = event -> { - if (mc.player != null && mc.world != null) { + if (client.player != null && client.level != null) { - Box box = new Box(mc.player.getPos().add(-150.0, -150.0, -150.0), - mc.player.getPos().add(150.0, 150.0, 150.0)); + AABB box = new AABB(client.player.position().add(-150.0, -150.0, -150.0), + client.player.position().add(150.0, 150.0, 150.0)); - for (ProjectileEntity projectile : mc.world.getEntitiesByClass(ProjectileEntity.class, box, + for (Projectile projectile : client.level.getEntitiesOfClass(Projectile.class, box, entity -> true)) { - if (!(projectile.getVelocity().lengthSquared() > 0.01) || projectile.isOnGround() - || mc.world.getBlockState(projectile.getBlockPos()).isSolidBlock(mc.world, - projectile.getBlockPos()) && Objects.requireNonNull(projectile.getOwner()).getId() != mc.player.getId()) { + if (!(projectile.getDeltaMovement().lengthSqr() > 0.01) || projectile.onGround() + || client.level.getBlockState(projectile.blockPosition()).isRedstoneConductor(client.level, + projectile.blockPosition()) && Objects.requireNonNull(projectile.getOwner()).getId() != client.player.getId()) { continue; } ParticleType type = getCurrentType(); - if (type != null && type instanceof ParticleEffect) { - mc.world.addParticle((ParticleEffect) type, projectile.getX(), projectile.getY(), + if (type instanceof ParticleOptions) { + client.level.addParticle((ParticleOptions) type, projectile.getX(), projectile.getY(), projectile.getZ(), 0.0, 0.0, 0.0); } } diff --git a/src/main/java/cn/pupperclient/management/mod/impl/settings/ModMenuSettings.java b/src/main/java/cn/pupperclient/management/mod/impl/settings/ModMenuSettings.java index 30d8722..31a0c0c 100644 --- a/src/main/java/cn/pupperclient/management/mod/impl/settings/ModMenuSettings.java +++ b/src/main/java/cn/pupperclient/management/mod/impl/settings/ModMenuSettings.java @@ -2,9 +2,10 @@ import java.util.Arrays; import java.util.Objects; - +import net.minecraft.client.gui.screens.Screen; import cn.pupperclient.PupperClient; import cn.pupperclient.gui.MusicPlayGui; +import net.minecraft.client.input.KeyEvent; import org.lwjgl.glfw.GLFW; import cn.pupperclient.event.EventBus; @@ -22,9 +23,7 @@ import cn.pupperclient.skia.font.Icon; import cn.pupperclient.utils.language.I18n; import cn.pupperclient.utils.language.Language; - -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.util.InputUtil; +import com.mojang.blaze3d.platform.InputConstants; public class ModMenuSettings extends Mod { @@ -32,20 +31,20 @@ public class ModMenuSettings extends Mod { private String previousLanguageOption = "language.english"; private boolean languageInitialized = false; - private KeybindSetting keybindSetting = new KeybindSetting("setting.keybind", "setting.keybind.description", - Icon.KEYBOARD, this, InputUtil.fromKeyCode(GLFW.GLFW_KEY_RIGHT_SHIFT, 0)); - private KeybindSetting keybindSetting_music = new KeybindSetting("setting.keybind_music", "setting.keybind_music.description", - Icon.KEYBOARD, this, InputUtil.fromKeyCode(GLFW.GLFW_KEY_M, 0)); - private BooleanSetting darkModeSetting = new BooleanSetting("setting.darkmode", "setting.darkmode.description", + private final KeybindSetting keybindSetting = new KeybindSetting("setting.keybind", "setting.keybind.description", + Icon.KEYBOARD, this, InputConstants.getKey(new KeyEvent(GLFW.GLFW_KEY_RIGHT_SHIFT, 0, 0))); + private final KeybindSetting keybindSetting_music = new KeybindSetting("setting.keybind_music", "setting.keybind_music.description", + Icon.KEYBOARD, this, InputConstants.getKey(new KeyEvent(GLFW.GLFW_KEY_M, 0, 0))); + private final BooleanSetting darkModeSetting = new BooleanSetting("setting.darkmode", "setting.darkmode.description", Icon.DARK_MODE, this, false); - private HctColorSetting hctColorSetting = new HctColorSetting("setting.color", "setting.color.description", + private final HctColorSetting hctColorSetting = new HctColorSetting("setting.color", "setting.color.description", Icon.PALETTE, this, Hct.from(220, 26, 6)); - private BooleanSetting blurSetting = new BooleanSetting("setting.blur", "setting.blur.description", Icon.LENS_BLUR, + private final BooleanSetting blurSetting = new BooleanSetting("setting.blur", "setting.blur.description", Icon.LENS_BLUR, this, true); - private NumberSetting blurIntensitySetting = new NumberSetting("setting.blurintensity", + private final NumberSetting blurIntensitySetting = new NumberSetting("setting.blurintensity", "setting.blurintensity.description", Icon.BLUR_LINEAR, this, 5, 1, 20, 1); - private ComboSetting languageSetting = new ComboSetting("setting.language", "setting.language.description", + private final ComboSetting languageSetting = new ComboSetting("setting.language", "setting.language.description", Icon.LANGUAGE, this, Arrays.asList("language.english", "language.chinese"), "language.english"); private Screen modMenu; @@ -97,11 +96,11 @@ private Language getLanguageEnumFromOption(String option) { } if (keybindSetting.isPressed()) { - mc.setScreen(new GuiModMenu()); + client.setScreen(new GuiModMenu()); } if (keybindSetting_music.isPressed()) { - mc.setScreen(new MusicPlayGui()); + client.setScreen(new MusicPlayGui()); } handleLanguageChange(); @@ -157,19 +156,7 @@ public NumberSetting getBlurIntensitySetting() { return blurIntensitySetting; } - public ComboSetting getLanguageSetting() { - return languageSetting; - } - public Screen getModMenu() { return modMenu; } - - public KeybindSetting getKeybindSetting_music() { - return keybindSetting_music; - } - - public void setKeybindSetting_music(KeybindSetting keybindSetting_music) { - this.keybindSetting_music = keybindSetting_music; - } } diff --git a/src/main/java/cn/pupperclient/management/mod/settings/impl/KeybindSetting.java b/src/main/java/cn/pupperclient/management/mod/settings/impl/KeybindSetting.java index d5df79c..06636fd 100644 --- a/src/main/java/cn/pupperclient/management/mod/settings/impl/KeybindSetting.java +++ b/src/main/java/cn/pupperclient/management/mod/settings/impl/KeybindSetting.java @@ -3,16 +3,15 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.management.mod.Mod; import cn.pupperclient.management.mod.settings.Setting; - -import net.minecraft.client.util.InputUtil; +import com.mojang.blaze3d.platform.InputConstants; public class KeybindSetting extends Setting { - private final InputUtil.Key defaultKey; - private InputUtil.Key key; + private final InputConstants.Key defaultKey; + private InputConstants.Key key; private boolean keyDown; private int pressTime; - public KeybindSetting(String name, String description, String icon, Mod parent, InputUtil.Key key) { + public KeybindSetting(String name, String description, String icon, Mod parent, InputConstants.Key key) { super(name, description, icon, parent); this.defaultKey = key; @@ -26,15 +25,15 @@ public void reset() { this.key = this.defaultKey; } - public InputUtil.Key getKey() { + public InputConstants.Key getKey() { return key; } - public void setKey(InputUtil.Key key) { + public void setKey(InputConstants.Key key) { this.key = key; } - public InputUtil.Key getDefaultKey() { + public InputConstants.Key getDefaultKey() { return defaultKey; } diff --git a/src/main/java/cn/pupperclient/management/quickplay/QuickPlay.java b/src/main/java/cn/pupperclient/management/quickplay/QuickPlay.java index f1cf945..ecb10e9 100644 --- a/src/main/java/cn/pupperclient/management/quickplay/QuickPlay.java +++ b/src/main/java/cn/pupperclient/management/quickplay/QuickPlay.java @@ -1,8 +1,7 @@ package cn.pupperclient.management.quickplay; import java.util.ArrayList; - -import net.minecraft.util.Identifier; +import net.minecraft.resources.Identifier; public class QuickPlay { diff --git a/src/main/java/cn/pupperclient/management/quickplay/impl/ArcadeQuickPlay.java b/src/main/java/cn/pupperclient/management/quickplay/impl/ArcadeQuickPlay.java index 499d344..942d7a0 100644 --- a/src/main/java/cn/pupperclient/management/quickplay/impl/ArcadeQuickPlay.java +++ b/src/main/java/cn/pupperclient/management/quickplay/impl/ArcadeQuickPlay.java @@ -2,13 +2,12 @@ import cn.pupperclient.management.quickplay.QuickPlay; import cn.pupperclient.management.quickplay.QuickPlayCommand; -import net.minecraft.util.Identifier; - import java.util.ArrayList; +import net.minecraft.resources.Identifier; public class ArcadeQuickPlay extends QuickPlay { public ArcadeQuickPlay() { - super("Arcade", Identifier.of("pupper/icons/hypixel/", "Arcade.png")); + super("Arcade", Identifier.fromNamespaceAndPath("pupper/icons/hypixel/", "Arcade.png")); } @Override diff --git a/src/main/java/cn/pupperclient/management/websocket/WebSocketManager.java b/src/main/java/cn/pupperclient/management/websocket/WebSocketManager.java index 522584c..04f39db 100644 --- a/src/main/java/cn/pupperclient/management/websocket/WebSocketManager.java +++ b/src/main/java/cn/pupperclient/management/websocket/WebSocketManager.java @@ -6,15 +6,13 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; - +import net.minecraft.client.Minecraft; +import net.minecraft.client.User; import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import cn.pupperclient.management.websocket.client.SoarWebSocketClient; import cn.pupperclient.management.websocket.packet.SoarPacket; import cn.pupperclient.utils.http.HttpUtils; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.session.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,7 +22,7 @@ public class WebSocketManager { private static final int MAX_RETRY_ATTEMPTS = 3; private static final int CONNECTION_CHECK_INTERVAL_SECONDS = 10; - private final MinecraftClient minecraftClient; + private final Minecraft minecraftClient; private final ScheduledExecutorService scheduler; private GameProfile currentGameProfile; @@ -33,7 +31,7 @@ public class WebSocketManager { private final boolean isShuttingDown = false; public WebSocketManager() { - this.minecraftClient = MinecraftClient.getInstance(); + this.minecraftClient = Minecraft.getInstance(); this.scheduler = Executors.newSingleThreadScheduledExecutor(r -> { Thread thread = new Thread(r, "WebSocket-Manager"); thread.setDaemon(true); @@ -82,7 +80,7 @@ private boolean shouldReconnect(GameProfile newProfile) { if (!currentGameProfile.equals(newProfile)) { LOGGER.info("User changed from {} to {}, reconnecting", - currentGameProfile.getName(), newProfile.getName()); + currentGameProfile.name(), newProfile.name()); retryCount = 0; return true; } @@ -135,15 +133,15 @@ private void closeExistingConnection() { private boolean authenticateWithMojang() { - Session session = minecraftClient.getSession(); - if (session == null || session.getAccessToken() == null || session.getUuidOrNull() == null) { + User session = minecraftClient.getUser(); + if (session == null || session.getAccessToken() == null || session.getProfileId() == null) { LOGGER.error("Invalid Minecraft session"); return false; } JsonObject authRequest = new JsonObject(); authRequest.addProperty("accessToken", session.getAccessToken()); - authRequest.addProperty("selectedProfile", session.getUuidOrNull().toString().replace("-", "")); + authRequest.addProperty("selectedProfile", session.getProfileId().toString().replace("-", "")); authRequest.addProperty("serverId", "cbd2c3f65d7ba5cceba0cc9647ff9a85c371f4"); try { @@ -159,8 +157,8 @@ private boolean authenticateWithMojang() { private SoarWebSocketClient createWebSocketClient() throws URISyntaxException { Map headers = new HashMap<>(); - headers.put("name", currentGameProfile.getName()); - headers.put("uuid", currentGameProfile.getId().toString().replace("-", "")); + headers.put("name", currentGameProfile.name()); + headers.put("uuid", currentGameProfile.id().toString().replace("-", "")); return new SoarWebSocketClient(headers, this::onConnectionFailure); } diff --git a/src/main/java/cn/pupperclient/mixin/interfaces/IMixinLivingEntity.java b/src/main/java/cn/pupperclient/mixin/interfaces/IMixinLivingEntity.java index 5b12dcd..c88dd00 100644 --- a/src/main/java/cn/pupperclient/mixin/interfaces/IMixinLivingEntity.java +++ b/src/main/java/cn/pupperclient/mixin/interfaces/IMixinLivingEntity.java @@ -1,7 +1,7 @@ package cn.pupperclient.mixin.interfaces; -import net.minecraft.util.Hand; +import net.minecraft.world.InteractionHand; public interface IMixinLivingEntity { - void soarClient_CN$fakeSwingHand(Hand hand); + void soarClient_CN$fakeSwingHand(InteractionHand hand); } diff --git a/src/main/java/cn/pupperclient/mixin/interfaces/IMixinMinecraftClient.java b/src/main/java/cn/pupperclient/mixin/interfaces/IMixinMinecraftClient.java index 26d9a2c..28efab4 100644 --- a/src/main/java/cn/pupperclient/mixin/interfaces/IMixinMinecraftClient.java +++ b/src/main/java/cn/pupperclient/mixin/interfaces/IMixinMinecraftClient.java @@ -3,5 +3,5 @@ import java.io.File; public interface IMixinMinecraftClient { - File getAssetDir(); + File pupper$getAssetDir(); } diff --git a/src/main/java/cn/pupperclient/mixin/interfaces/IRenderPipeline.java b/src/main/java/cn/pupperclient/mixin/interfaces/IRenderPipeline.java new file mode 100644 index 0000000..2ee5120 --- /dev/null +++ b/src/main/java/cn/pupperclient/mixin/interfaces/IRenderPipeline.java @@ -0,0 +1,11 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.mixin.interfaces; + +public interface IRenderPipeline { + void pupper$setLineSmooth(boolean lineSmooth); + + boolean pupper$getLineSmooth(); +} diff --git a/src/main/java/cn/pupperclient/mixin/mixins/accessors/GameRendererAccessor.java b/src/main/java/cn/pupperclient/mixin/mixins/accessors/GameRendererAccessor.java new file mode 100644 index 0000000..3fc54fe --- /dev/null +++ b/src/main/java/cn/pupperclient/mixin/mixins/accessors/GameRendererAccessor.java @@ -0,0 +1,16 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.mixin.mixins.accessors; + +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.fog.FogRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(GameRenderer.class) +public interface GameRendererAccessor { + @Accessor("fogRenderer") + FogRenderer pupper$fogRenderer(); +} diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinClientBrandRetriever.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinClientBrandRetriever.java index 7e940d4..03dce26 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinClientBrandRetriever.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinClientBrandRetriever.java @@ -2,7 +2,6 @@ import cn.pupperclient.PupperClient; import net.minecraft.client.ClientBrandRetriever; -import net.minecraft.obfuscate.DontObfuscate; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -12,9 +11,8 @@ public class MixinClientBrandRetriever { * @author oneachina * @reason Set Pupper Brand */ - @DontObfuscate @Overwrite public static String getClientModName() { - return PupperClient.getInstance().getName() + "(" + PupperClient.getInstance().getVersion() + ")"; + return PupperClient.getInstance().getName() + " (" + PupperClient.getInstance().getVersion() + ") "; } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinKeyboard.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinKeyboard.java index 419e688..137ff64 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinKeyboard.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinKeyboard.java @@ -10,24 +10,22 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.management.mod.settings.impl.KeybindSetting; +import com.mojang.blaze3d.platform.InputConstants; +import net.minecraft.client.KeyboardHandler; -import net.minecraft.client.Keyboard; -import net.minecraft.client.util.InputUtil; - -@Mixin(Keyboard.class) +@Mixin(KeyboardHandler.class) public abstract class MixinKeyboard { - @Inject( - method = "onKey(JIIII)V", + method = "keyPress(JILnet/minecraft/client/input/KeyEvent;)V", at = @At( value = "INVOKE", - target = "Lnet/minecraft/client/option/KeyBinding;onKeyPressed(Lnet/minecraft/client/util/InputUtil$Key;)V", + target = "Lnet/minecraft/client/KeyMapping;click(Lcom/mojang/blaze3d/platform/InputConstants$Key;)V", shift = At.Shift.AFTER ) ) - private void onKeyPressed(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) { + private void onKeyPressed(long handle, int action, net.minecraft.client.input.KeyEvent event, CallbackInfo ci) { if (action == GLFW.GLFW_PRESS || action == GLFW.GLFW_REPEAT) { - InputUtil.Key inputKey = InputUtil.fromKeyCode(key, scancode); + InputConstants.Key inputKey = InputConstants.getKey(event); for (KeybindSetting setting : PupperClient.getInstance().getModManager().getKeybindSettings()) { if (setting.getKey().equals(inputKey)) { setting.setPressed(); @@ -38,16 +36,16 @@ private void onKeyPressed(long window, int key, int scancode, int action, int mo } @Inject( - method = "onKey(JIIII)V", + method = "keyPress(JILnet/minecraft/client/input/KeyEvent;)V", at = @At( value = "INVOKE", - target = "Lnet/minecraft/client/option/KeyBinding;setKeyPressed(Lnet/minecraft/client/util/InputUtil$Key;Z)V", + target = "Lnet/minecraft/client/KeyMapping;set(Lcom/mojang/blaze3d/platform/InputConstants$Key;Z)V", shift = At.Shift.AFTER ) ) - private void onKeyReleased(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) { + private void onKeyReleased(long handle, int action, net.minecraft.client.input.KeyEvent event, CallbackInfo ci) { if (action == GLFW.GLFW_RELEASE) { - InputUtil.Key inputKey = InputUtil.fromKeyCode(key, scancode); + InputConstants.Key inputKey = InputConstants.getKey(event); for (KeybindSetting setting : PupperClient.getInstance().getModManager().getKeybindSettings()) { if (setting.getKey().equals(inputKey)) { setting.setKeyDown(false); @@ -56,13 +54,11 @@ private void onKeyReleased(long window, int key, int scancode, int action, int m } } - @Inject( - at = {@At("HEAD")}, - method = {"onKey"} - ) - private void onKeyPress(long pWindowPointer, int pKey, int pScanCode, int pAction, int pModifiers, CallbackInfo ci) { - if (pKey != -1 && PupperClient.getInstance() != null && EventBus.getInstance() != null) { - EventBus.getInstance().post(new KeyEvent(pKey, pAction != 0)); + @Inject(method = "keyPress(JILnet/minecraft/client/input/KeyEvent;)V", at = @At("HEAD")) + private void onKeyPress(long handle, int action, net.minecraft.client.input.KeyEvent event, CallbackInfo ci) { + int key = event.key(); + if (key != -1 && EventBus.getInstance() != null) { + EventBus.getInstance().post(new KeyEvent(key, action != 0)); } } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinMinecraftClient.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinMinecraftClient.java index b60ca3c..4edd8b5 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinMinecraftClient.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinMinecraftClient.java @@ -3,10 +3,30 @@ import java.io.File; import java.io.IOException; -import cn.pupperclient.shader.impl.Kawaseblur; -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.gui.screen.Screen; +import cn.pupperclient.event.client.ResolutionChangedEvent; +import cn.pupperclient.event.skia.DrawSkiaEvent; +import cn.pupperclient.skia.Skia; +import net.minecraft.client.Minecraft; +import net.minecraft.client.Options; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.main.GameConfig; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.multiplayer.MultiPlayerGameMode; +import net.minecraft.client.particle.ParticleEngine; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.HitResult.Type; +import cn.pupperclient.event.skia.RenderSkiaEvent; +import com.mojang.blaze3d.platform.Window; import org.jetbrains.annotations.Nullable; +import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -28,22 +48,7 @@ import cn.pupperclient.mixin.interfaces.IMixinMinecraftClient; import cn.pupperclient.skia.context.SkiaContext; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.RunArgs; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.client.option.GameOptions; -import net.minecraft.client.particle.ParticleManager; -import net.minecraft.client.util.Window; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.hit.HitResult; -import net.minecraft.util.hit.HitResult.Type; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; - -@Mixin(value = MinecraftClient.class, priority = 300) +@Mixin(value = Minecraft.class, priority = 300) public abstract class MixinMinecraftClient implements IMixinMinecraftClient { @Shadow @@ -51,29 +56,34 @@ public abstract class MixinMinecraftClient implements IMixinMinecraftClient { private Window window; @Shadow - public int attackCooldown; + public int missTime; @Shadow - public ClientPlayerInteractionManager interactionManager; + public MultiPlayerGameMode gameMode; @Final @Shadow - public ParticleManager particleManager; + public ParticleEngine particleEngine; - @Shadow - public GameOptions options; + @Final + @Shadow + public Options options; @Shadow - public HitResult crosshairTarget; + public HitResult hitResult; @Shadow - public ClientWorld world; + public ClientLevel level; @Shadow - public ClientPlayerEntity player; + public LocalPlayer player; + + @Shadow + @Nullable + public Screen screen; @Shadow - protected abstract String getWindowTitle(); + protected abstract String createTitle(); @Shadow public abstract void setScreen(@Nullable Screen screen); @@ -81,42 +91,52 @@ public abstract class MixinMinecraftClient implements IMixinMinecraftClient { @Unique private File assetDir; - @Inject(method = "(Lnet/minecraft/client/RunArgs;)V", at = @At("TAIL")) - public void onInit(RunArgs args, CallbackInfo ci) { - assetDir = args.directories.assetDir; + @Inject(method = "(Lnet/minecraft/client/main/GameConfig;)V", at = @At("TAIL")) + public void onInit(GameConfig args, CallbackInfo ci) { + assetDir = args.location.assetDirectory; } - @Inject(method = "stop", at = @At("HEAD")) + @Inject(method = "destroy", at = @At("HEAD")) public void onStop(CallbackInfo ci) { PupperClient.getInstance().getConfigManager().save(ConfigType.MOD); } - @Inject(method = "handleBlockBreaking", at = @At("HEAD")) + @Inject(method = "continueAttack", at = @At("HEAD")) private void handleBlockBreaking(boolean breaking, CallbackInfo ci) { if (OldAnimationsMod.getInstance().isEnabled() && OldAnimationsMod.getInstance().isOldBreaking()) { - if (this.options.attackKey.isPressed() && this.options.useKey.isPressed()) { + if (this.options.keyAttack.isDown() && this.options.keyUse.isDown()) { - if (breaking && this.crosshairTarget != null && this.crosshairTarget.getType() == Type.BLOCK) { + if (breaking && this.hitResult != null && this.hitResult.getType() == Type.BLOCK) { - BlockHitResult blockHitResult = (BlockHitResult) this.crosshairTarget; + BlockHitResult blockHitResult = (BlockHitResult) this.hitResult; BlockPos blockPos = blockHitResult.getBlockPos(); + BlockState blockState = level.getBlockState(blockPos); + + if (!blockState.isAir()) { + Direction direction = blockHitResult.getDirection(); + BlockParticleOption particleOption = new BlockParticleOption(ParticleTypes.BLOCK, blockState); + + double x = blockPos.getX() + 0.5 + direction.getStepX() * 0.5; + double y = blockPos.getY() + 0.5 + direction.getStepY() * 0.5; + double z = blockPos.getZ() + 0.5 + direction.getStepZ() * 0.5; + + double xSpeed = direction.getStepX() * 0.2; + double ySpeed = 0.1; + double zSpeed = direction.getStepZ() * 0.2; - if (!this.world.getBlockState(blockPos).isAir()) { - Direction direction = blockHitResult.getSide(); - this.particleManager.addBlockBreakingParticles(blockPos, direction); - ((IMixinLivingEntity) player).soarClient_CN$fakeSwingHand(Hand.MAIN_HAND); + level.addParticle(particleOption, x, y, z, xSpeed, ySpeed, zSpeed); + ((IMixinLivingEntity) player).soarClient_CN$fakeSwingHand(InteractionHand.MAIN_HAND); } } } } } - @Inject(method = "doAttack", at = @At("HEAD")) + @Inject(method = "startAttack", at = @At("HEAD")) private void onHitDelayFix(CallbackInfoReturnable cir) { if (HitDelayFixMod.getInstance().isEnabled()) { - attackCooldown = 0; - RenderSystem.defaultBlendFunc(); + missTime = 0; } } @@ -125,18 +145,26 @@ private void onHitDelayFix(CallbackInfoReturnable cir) { * @reason updateWindowTitle */ @Overwrite - public void updateWindowTitle() { + public void updateTitle() { this.window.setTitle(PupperClient.getInstance().getName() + " | " + PupperClient.getInstance().getVersion() + " for " - + getWindowTitle()); + + createTitle()); } @Inject(method = "", at = @At("TAIL")) public void init(CallbackInfo ci) throws IOException { - SkiaContext.createSurface(window.getWidth(), window.getHeight()); PupperClient.getInstance().start(); } - @Inject(method = "stop", at = @At("HEAD")) + @Inject(method = "", at = @At("RETURN")) + public void skia(CallbackInfo ci) throws IOException { + int[] width = new int[1]; + int[] height = new int[1]; + + GLFW.glfwGetFramebufferSize(Minecraft.getInstance().getWindow().handle(), width, height); + SkiaContext.createSurface(width[0] > 0 ? width[0] : 1, height[0] > 0 ? height[0] : 1, null); + } + + @Inject(method = "destroy", at = @At("HEAD")) public void onShutdown(CallbackInfo ci) { PupperClient.getInstance().onShutdown(); } @@ -146,19 +174,43 @@ public void onClientTick(CallbackInfo ci) { EventBus.getInstance().post(new ClientTickEvent()); } - @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;printCrashReport()V")) + @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/SingleTickProfiler;createTickProfiler(Ljava/lang/String;)Lnet/minecraft/util/profiling/SingleTickProfiler;")) public void onGameLoop(CallbackInfo ci) { EventBus.getInstance().post(new GameLoopEvent()); } - @Inject(method = "onResolutionChanged", at = @At("TAIL")) - public void onResolutionChanged(CallbackInfo info) { - Kawaseblur.GUI_BLUR.resize(); - Kawaseblur.INGAME_BLUR.resize(); - } + @Inject( + method = {"renderFrame"}, + at = @At( + value = "INVOKE", + target = "Lcom/mojang/blaze3d/systems/RenderSystem;flipFrame(Lcom/mojang/blaze3d/TracyFrameCapture;)V" + ) + ) + private void onBeforeFlipFrame(CallbackInfo ci) { + if (level == null) { + return; + } + SkiaContext.draw((canvas) -> { + Skia.save(); + Skia.scale((float) Minecraft.getInstance().getWindow().getGuiScale()); + EventBus.getInstance().post(new RenderSkiaEvent(canvas)); + Skia.restore(); + }); + + SkiaContext.draw((canvas) -> { + Skia.save(); + EventBus.getInstance().post(new DrawSkiaEvent(canvas)); + Skia.restore(); + }); + } @Override - public File getAssetDir() { + public File pupper$getAssetDir() { return this.assetDir; } + + @Inject(method = "resizeGui", at = @At("TAIL")) + private void onResizeGui(CallbackInfo ci) { + EventBus.getInstance().post(new ResolutionChangedEvent()); + } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinMouse.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinMouse.java index 8253540..c36543c 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinMouse.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/MixinMouse.java @@ -3,8 +3,7 @@ import cn.pupperclient.PupperClient; import cn.pupperclient.event.client.MouseClickEvent; import cn.pupperclient.management.mod.impl.hud.CPSDisplayMod; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.util.Window; +import net.minecraft.client.input.MouseButtonInfo; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -14,79 +13,74 @@ import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.MouseScrollEvent; import cn.pupperclient.management.mod.settings.impl.KeybindSetting; +import com.mojang.blaze3d.platform.InputConstants.Type; +import com.mojang.blaze3d.platform.Window; +import net.minecraft.client.Minecraft; +import net.minecraft.client.MouseHandler; -import net.minecraft.client.Mouse; -import net.minecraft.client.util.InputUtil.Type; - -@Mixin(Mouse.class) +@Mixin(MouseHandler.class) public abstract class MixinMouse { - @Inject(method = "onMouseButton", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/KeyBinding;onKeyPressed(Lnet/minecraft/client/util/InputUtil$Key;)V", shift = At.Shift.AFTER)) - public void onPressed(long window, int button, int action, int mods, CallbackInfo ci) { - - for (KeybindSetting s : PupperClient.getInstance().getModManager().getKeybindSettings()) { - - if (s.getKey().equals(Type.MOUSE.createFromCode(button))) { - - if (action == GLFW.GLFW_PRESS) { - s.setPressed(); - } - - s.setKeyDown(true); - } - } - } + @Inject(method = "onButton", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyMapping;click(Lcom/mojang/blaze3d/platform/InputConstants$Key;)V", shift = At.Shift.AFTER)) + private void onButtonPressed(long handle, MouseButtonInfo rawButtonInfo, int action, CallbackInfo ci) { + int button = rawButtonInfo.button(); + if (action == GLFW.GLFW_PRESS) { + for (KeybindSetting s : PupperClient.getInstance().getModManager().getKeybindSettings()) { + if (s.getKey().equals(Type.MOUSE.getOrCreate(button))) { + s.setPressed(); + s.setKeyDown(true); + } + } + } + } - @Inject(method = "onMouseButton", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/KeyBinding;setKeyPressed(Lnet/minecraft/client/util/InputUtil$Key;Z)V", shift = At.Shift.AFTER, ordinal = 0)) - public void onReleased(long window, int button, int action, int mods, CallbackInfo ci) { - for (KeybindSetting s : PupperClient.getInstance().getModManager().getKeybindSettings()) { - if (s.getKey().equals(Type.MOUSE.createFromCode(button))) { - s.setKeyDown(false); - } - } - } + @Inject(method = "onButton", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyMapping;set(Lcom/mojang/blaze3d/platform/InputConstants$Key;Z)V", shift = At.Shift.AFTER)) + private void onButtonReleased(long window, MouseButtonInfo rawButtonInfo, int action, CallbackInfo ci) { + int button = rawButtonInfo.button(); + if (action == GLFW.GLFW_RELEASE) { + for (KeybindSetting s : PupperClient.getInstance().getModManager().getKeybindSettings()) { + if (s.getKey().equals(Type.MOUSE.getOrCreate(button))) { + s.setKeyDown(false); + } + } + } + } - @Inject(method = "onMouseButton", at = @At("HEAD")) - private void onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) { + @Inject(method = "onButton", at = @At("HEAD")) + private void onMouseButtonEvent(long window, MouseButtonInfo rawButtonInfo, int action, CallbackInfo ci) { if (action == GLFW.GLFW_PRESS) { - MinecraftClient client = MinecraftClient.getInstance(); - if (client == null) return; + Minecraft client = Minecraft.getInstance(); - double rawX = client.mouse.getX(); - double rawY = client.mouse.getY(); + double rawX = client.mouseHandler.xpos(); + double rawY = client.mouseHandler.ypos(); Window win = client.getWindow(); - double scaleFactor = win.getScaleFactor(); + double scaleFactor = win.getGuiScale(); double scaledX = rawX / scaleFactor; - double scaledY = win.getScaledHeight() - (rawY / scaleFactor); + double scaledY = win.getGuiScaledHeight() - (rawY / scaleFactor); - EventBus.getInstance().post(new MouseClickEvent(button, scaledX, scaledY)); + EventBus.getInstance().post(new MouseClickEvent(rawButtonInfo.button(), scaledX, scaledY)); } } - @Inject(method = "onMouseScroll", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerInventory;setSelectedSlot(I)V", shift = At.Shift.BEFORE), cancellable = true) - private void onMouseScroll(long window, double horizontal, double vertical, CallbackInfo ci) { - - MouseScrollEvent event = new MouseScrollEvent(vertical); - - EventBus.getInstance().post(event); + @Inject(method = "onScroll", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Inventory;setSelectedSlot(I)V"), cancellable = true) + private void onMouseScroll(long window, double x_offset, double y_offset, CallbackInfo ci) { + MouseScrollEvent event = new MouseScrollEvent(y_offset); + EventBus.getInstance().post(event); + if (event.isCancelled()) { + ci.cancel(); + } + } - if (event.isCancelled()) { - ci.cancel(); - } - } + @Inject(method = "onButton", at = @At("HEAD")) + private void onMouseButtonForCPS(long window, MouseButtonInfo rawButtonInfo, int action, CallbackInfo ci) { + if (action != GLFW.GLFW_PRESS) return; - @Inject(method = "onMouseButton", at = @At("HEAD")) - public void onMouseButtonForCPS(long window, int button, int action, int mods, CallbackInfo ci) { - CPSDisplayMod cpsDisplayMod = PupperClient.getInstance().getModManager().getMods() + PupperClient.getInstance().getModManager().getMods() .stream() .filter(mod -> mod instanceof CPSDisplayMod) .map(mod -> (CPSDisplayMod) mod) - .findFirst() - .orElse(null); + .findFirst().ifPresent(cpsDisplayMod -> cpsDisplayMod.onMouseClick(rawButtonInfo.button(), true)); - if (cpsDisplayMod != null && action == GLFW.GLFW_PRESS) { - cpsDisplayMod.onMouseClick(button, true); - } } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinBossBarHud.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinBossBarHud.java index 28ce71e..bdc314d 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinBossBarHud.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinBossBarHud.java @@ -1,83 +1,138 @@ package cn.pupperclient.mixin.mixins.minecraft.client.gui; -import java.util.Map; -import java.util.UUID; - +import cn.pupperclient.management.mod.api.Position; +import cn.pupperclient.management.mod.impl.hud.BossBarMod; +import com.google.common.collect.Maps; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.BossHealthOverlay; +import net.minecraft.client.gui.components.LerpingBossEvent; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; +import net.minecraft.util.Mth; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.BossEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +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 com.google.common.collect.Maps; -import cn.pupperclient.management.mod.api.Position; -import cn.pupperclient.management.mod.impl.hud.BossBarMod; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.hud.BossBarHud; -import net.minecraft.client.gui.hud.ClientBossBar; -import net.minecraft.entity.boss.BossBar; -import net.minecraft.text.Text; -import net.minecraft.util.profiler.Profiler; -import net.minecraft.util.profiler.Profilers; +import java.util.Map; +import java.util.UUID; -@Mixin(BossBarHud.class) +@Mixin(BossHealthOverlay.class) public abstract class MixinBossBarHud { - @Shadow - @Final - private MinecraftClient client; - - @Shadow - @Final - final Map bossBars = Maps.newLinkedHashMap(); - - @Shadow - public abstract void renderBossBar(DrawContext context, int x, int y, BossBar bossBar); - - @Inject(method = "render", at = @At("HEAD"), cancellable = true) - private void render(DrawContext context, CallbackInfo ci) { - - BossBarMod mod = BossBarMod.getInstance(); - - if (mod.isEnabled() && !mod.isVanillaPosition()) { - Position position = mod.getPosition(); - onCustomRender(context, (int) position.getX(), (int) position.getY()); - position.setScale(1.0F); - position.setSize(182, 14); - ci.cancel(); - } else if (!mod.isEnabled()) { - ci.cancel(); - } - } - - public void onCustomRender(DrawContext context, int x, int y) { - - if (!this.bossBars.isEmpty()) { - - Profiler profiler = Profilers.get(); - profiler.push("bossHealth"); - int j = y; - - for (ClientBossBar clientBossBar : this.bossBars.values()) { - - Text text = clientBossBar.getName(); - int m = this.client.textRenderer.getWidth(text); - int n = x - m / 2; - context.drawTextWithShadow(this.client.textRenderer, text, n, j, 16777215); - - int k = x - 91; - this.renderBossBar(context, k, j + 9, clientBossBar); - - j += 10 + 9; - if (j >= context.getScaledWindowHeight() / 3) { - break; - } - } - - profiler.pop(); - } - } + @Shadow + @Final + private Minecraft minecraft; + + @Shadow + @Final + private Map events = Maps.newLinkedHashMap(); + + @Shadow + private void extractBar(GuiGraphicsExtractor graphics, int x, int y, BossEvent event, int width, Identifier[] sprites, Identifier[] overlaySprites) { + } + + @Inject(method = "extractRenderState", at = @At("HEAD"), cancellable = true) + private void onExtractRenderState(GuiGraphicsExtractor graphics, CallbackInfo ci) { + BossBarMod mod = BossBarMod.getInstance(); + + if (mod.isEnabled()) { + if (!mod.isVanillaPosition()) { + Position position = mod.getPosition(); + onCustomRender(graphics, (int) position.getX(), (int) position.getY()); + position.setScale(1.0F); + position.setSize(182, 14); + ci.cancel(); + } + } else { + ci.cancel(); + } + } + + @Unique + private void onCustomRender(GuiGraphicsExtractor graphics, int x, int y) { + if (!this.events.isEmpty()) { + ProfilerFiller profiler = Profiler.get(); + profiler.push("bossHealth"); + + int currentY = y; + for (LerpingBossEvent event : this.events.values()) { + Component name = event.getName(); + int textWidth = this.minecraft.font.width(name); + int textX = x - textWidth / 2; + graphics.text(this.minecraft.font, name, textX, currentY, -1); + + int barX = x - 91; + int barY = currentY + 9; + this.drawCustomBar(graphics, barX, barY, event); + + currentY += 19; // 10 + 9 + if (currentY >= graphics.guiHeight() / 3) { + break; + } + } + + profiler.pop(); + } + } + + @Unique + private void drawCustomBar(GuiGraphicsExtractor graphics, int x, int y, BossEvent event) { + // 绘制背景 + Identifier[] bgSprites = new Identifier[]{ + Identifier.withDefaultNamespace("boss_bar/pink_background"), + Identifier.withDefaultNamespace("boss_bar/blue_background"), + Identifier.withDefaultNamespace("boss_bar/red_background"), + Identifier.withDefaultNamespace("boss_bar/green_background"), + Identifier.withDefaultNamespace("boss_bar/yellow_background"), + Identifier.withDefaultNamespace("boss_bar/purple_background"), + Identifier.withDefaultNamespace("boss_bar/white_background") + }; + Identifier[] progressSprites = new Identifier[]{ + Identifier.withDefaultNamespace("boss_bar/pink_progress"), + Identifier.withDefaultNamespace("boss_bar/blue_progress"), + Identifier.withDefaultNamespace("boss_bar/red_progress"), + Identifier.withDefaultNamespace("boss_bar/green_progress"), + Identifier.withDefaultNamespace("boss_bar/yellow_progress"), + Identifier.withDefaultNamespace("boss_bar/purple_progress"), + Identifier.withDefaultNamespace("boss_bar/white_progress") + }; + Identifier[] overlayBgSprites = new Identifier[]{ + Identifier.withDefaultNamespace("boss_bar/notched_6_background"), + Identifier.withDefaultNamespace("boss_bar/notched_10_background"), + Identifier.withDefaultNamespace("boss_bar/notched_12_background"), + Identifier.withDefaultNamespace("boss_bar/notched_20_background") + }; + Identifier[] overlayProgressSprites = new Identifier[]{ + Identifier.withDefaultNamespace("boss_bar/notched_6_progress"), + Identifier.withDefaultNamespace("boss_bar/notched_10_progress"), + Identifier.withDefaultNamespace("boss_bar/notched_12_progress"), + Identifier.withDefaultNamespace("boss_bar/notched_20_progress") + }; + + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, + bgSprites[event.getColor().ordinal()], 182, 5, 0, 0, x, y, 182, 5); + if (event.getOverlay() != BossEvent.BossBarOverlay.PROGRESS) { + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, + overlayBgSprites[event.getOverlay().ordinal() - 1], 182, 5, 0, 0, x, y, 182, 5); + } + + int progressWidth = Mth.lerpDiscrete(event.getProgress(), 0, 182); + if (progressWidth > 0) { + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, + progressSprites[event.getColor().ordinal()], 182, 5, 0, 0, x, y, progressWidth, 5); + if (event.getOverlay() != BossEvent.BossBarOverlay.PROGRESS) { + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, + overlayProgressSprites[event.getOverlay().ordinal() - 1], 182, 5, 0, 0, x, y, progressWidth, 5); + } + } + } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinChatHud.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinChatHud.java index 988c507..d079970 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinChatHud.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinChatHud.java @@ -2,18 +2,18 @@ import cn.pupperclient.event.EventBus; import cn.pupperclient.event.server.ChatEvent; -import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.ChatComponent; +import net.minecraft.network.chat.Component; 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(ChatHud.class) +@Mixin(ChatComponent.class) public abstract class MixinChatHud { - @Inject(method = "addMessage(Lnet/minecraft/text/Text;)V", at = @At("HEAD")) - private void onChatMessage(Text message, CallbackInfo ci) { + @Inject(method = "addClientSystemMessage", at = @At("HEAD")) + private void onChatMessage(Component message, CallbackInfo ci) { String rawMessage = message.getString(); if (rawMessage.startsWith("§7[§bPupper§7]")) return; ChatEvent event = new ChatEvent(rawMessage); diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinLanguageScreen.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinLanguageScreen.java index f1132de..6516fdf 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinLanguageScreen.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinLanguageScreen.java @@ -1,23 +1,22 @@ package cn.pupperclient.mixin.mixins.minecraft.client.gui; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.option.LanguageOptionsScreen; -import net.minecraft.text.Text; 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; -import static cn.pupperclient.utils.minecraft.interfaces.IMinecraft.mc; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.options.LanguageSelectScreen; +import net.minecraft.network.chat.Component; -@Mixin(value = LanguageOptionsScreen.class, priority = 1001) +@Mixin(value = LanguageSelectScreen.class, priority = 1001) public class MixinLanguageScreen extends Screen { - protected MixinLanguageScreen(Text title) { + protected MixinLanguageScreen(Component title) { super(title); } @Inject(method = "onDone", at = @At("TAIL")) public void onDone(CallbackInfo ci) { - mc.inGameHud.getChatHud().reset(); + minecraft.gui.getChat().rescaleChat(); } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinMultiplayerScreen.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinMultiplayerScreen.java index 32fdd8f..9d95e6b 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinMultiplayerScreen.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinMultiplayerScreen.java @@ -7,21 +7,20 @@ import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.ServerJoinEvent; +import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; +import net.minecraft.client.multiplayer.ServerData; -import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; -import net.minecraft.client.network.ServerInfo; - -@Mixin(MultiplayerScreen.class) +@Mixin(JoinMultiplayerScreen.class) public class MixinMultiplayerScreen { - @Inject(method = "connect(Lnet/minecraft/client/network/ServerInfo;)V", at = @At("HEAD")) - private void onConnect(ServerInfo server, CallbackInfo ci) { - EventBus.getInstance().post(new ServerJoinEvent(server.address)); + @Inject(method = "join(Lnet/minecraft/client/multiplayer/ServerData;)V", at = @At("HEAD")) + private void onConnect(ServerData server, CallbackInfo ci) { + EventBus.getInstance().post(new ServerJoinEvent(server.ip)); } @Inject(method = "removed", at = @At("HEAD"), cancellable = true) public void onRemoved(CallbackInfo ci) { - if (((MultiplayerScreen) (Object) this).serverListWidget == null) { + if (((JoinMultiplayerScreen) (Object) this).serverSelectionList == null) { ci.cancel(); } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinPackScreen.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinPackScreen.java index 269bddc..a1ec59d 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinPackScreen.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinPackScreen.java @@ -6,30 +6,25 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import cn.pupperclient.gui.GuiResourcePackConvert; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.packs.PackSelectionScreen; +import net.minecraft.network.chat.Component; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.pack.PackScreen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.text.Text; - -@Mixin(PackScreen.class) +@Mixin(PackSelectionScreen.class) public class MixinPackScreen extends Screen { - protected MixinPackScreen(Text title) { + protected MixinPackScreen(Component title) { super(title); } @Inject(method = "init", at = @At("HEAD")) private void onInit(CallbackInfo ci) { - ButtonWidget.Builder builder = ButtonWidget - .builder(Text.of("Convert"), button -> { - if (client != null) { - client.setScreen(new GuiResourcePackConvert(this)); - } - }).size(98, 20); + Button.Builder builder = Button + .builder(Component.nullToEmpty("Convert"), _ -> minecraft.setScreen(new GuiResourcePackConvert(this))).size(98, 20); - builder.position(width - 98 - 5, 5); - this.addDrawableChild(builder.build()); + builder.pos(width - 98 - 5, 5); + this.addRenderableWidget(builder.build()); } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinSplashScreen.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinSplashScreen.java index 534c732..318c1fa 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinSplashScreen.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinSplashScreen.java @@ -1,387 +1,9 @@ package cn.pupperclient.mixin.mixins.minecraft.client.gui; -import cn.pupperclient.skia.Skia; -import cn.pupperclient.skia.context.SkiaContext; -import cn.pupperclient.skia.font.Fonts; -import io.github.humbleui.skija.Canvas; -import io.github.humbleui.skija.Font; -import io.github.humbleui.types.Rect; -import java.awt.Color; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.SplashOverlay; -import net.minecraft.client.texture.ResourceTexture; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; -import org.lwjgl.glfw.GLFW; -import org.spongepowered.asm.mixin.Final; +import net.minecraft.client.gui.screens.LoadingOverlay; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -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.Optional; -import java.util.function.Consumer; - -@Mixin(SplashOverlay.class) +@Mixin(LoadingOverlay.class) public abstract class MixinSplashScreen { - @Shadow @Final private MinecraftClient client; - @Shadow @Final private boolean reloading; - @Shadow @Final private Consumer> exceptionHandler; - - // Animation timing variables - @Unique private long soar_animationStartTime = -1L; - @Unique private long soar_reloadStartTime = -1L; - @Unique private static final long MAX_RELOAD_TIME = 15_000L; - @Unique private static final Identifier CUSTOM_LOGO = Identifier.of("pupper", "logo.png"); - @Unique private static final int LOGO_ACTUAL_SIZE = 1080; - @Unique private static final float LOGO_SCALE = 0.15f; - @Unique private static final long ANIMATION_TOTAL_TIME = 4500L; - @Unique private static final long FADE_DURATION = 500L; - @Unique private static final long WELCOME_DISPLAY_TIME = 5000L; // 5 second display time - @Unique private static final long TAP_PROMPT_DELAY = 0; - @Unique private static final long TTS_CYCLE_DURATION = 2000L; // 2-second cycle for TTS animation - @Unique private static final long CLICK_FADE_DURATION = 2000L; // 2 second fade out after click - @Unique private static final int PROGRESS_BAR_HEIGHT = 8; - - // State variables - @Unique private int lastWindowWidth = -1; - @Unique private int lastWindowHeight = -1; - @Unique private boolean skipNextFrame = false; - @Unique private boolean welcomeDisplayed = false; - @Unique private boolean tapPromptDisplayed = false; - @Unique private boolean tapClicked = false; - @Unique private long welcomeStartTime = -1L; - @Unique private long tapPromptStartTime = -1L; - @Unique private long tapClickTime = -1L; - - @Unique - private void ensureLogoTexture() { - var tm = this.client.getTextureManager(); - if (tm.getTexture(CUSTOM_LOGO) == null) { - tm.registerTexture(CUSTOM_LOGO, new ResourceTexture(CUSTOM_LOGO)); - } - } - - @Inject(method = "render", at = @At("HEAD"), cancellable = true) - private void pupper_takeOverAndRender(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - int width = MinecraftClient.getInstance().getWindow().getWidth(); - int height = MinecraftClient.getInstance().getWindow().getHeight(); - - // Recreate surface if window size changed - if (lastWindowWidth != width || lastWindowHeight != height) { - SkiaContext.createSurface(width, height); - lastWindowWidth = width; - lastWindowHeight = height; - } - - if (width <= 0 || height <= 0) { - return; - } - - ci.cancel(); - - SkiaContext.draw(canvas -> { - renderWithSkia(canvas, width, height, mouseX, mouseY); - }); - } - - @Unique - private void renderWithSkia(Canvas canvas, int width, int height, int mouseX, int mouseY) { - ensureLogoTexture(); - - // Handle reloading state - if (this.reloading) { - if (this.soar_reloadStartTime == -1L) this.soar_reloadStartTime = Util.getMeasuringTimeMs(); - this.soar_animationStartTime = -1L; - this.welcomeDisplayed = false; - this.tapPromptDisplayed = false; - this.tapClicked = false; - this.welcomeStartTime = -1L; - this.tapPromptStartTime = -1L; - this.tapClickTime = -1L; - - long reloadElapsed = Util.getMeasuringTimeMs() - this.soar_reloadStartTime; - if (reloadElapsed > MAX_RELOAD_TIME) { - try { - this.client.setOverlay(null); - this.exceptionHandler.accept(Optional.empty()); - } catch (Exception ignored) {} - this.soar_reloadStartTime = -1L; - return; - } - - renderLoadingScreen(width, height, reloadElapsed, 1.0f, false); - return; - } - - this.soar_reloadStartTime = -1L; - if (this.soar_animationStartTime == -1L) { - this.soar_animationStartTime = Util.getMeasuringTimeMs(); - } - - long timePassed = Util.getMeasuringTimeMs() - this.soar_animationStartTime; - - // Check if welcome screen should be displayed - if (timePassed >= ANIMATION_TOTAL_TIME && !welcomeDisplayed) { - welcomeDisplayed = true; - welcomeStartTime = Util.getMeasuringTimeMs(); - tapPromptDisplayed = false; - tapClicked = false; - } - - // Welcome screen logic - if (welcomeDisplayed) { - long welcomeTimePassed = Util.getMeasuringTimeMs() - welcomeStartTime; - - // Check if tap prompt should be displayed (1-second delay) - if (!tapPromptDisplayed) { - tapPromptDisplayed = true; - tapPromptStartTime = Util.getMeasuringTimeMs(); - } - - // Check if tap prompt was clicked - if (!tapClicked && GLFW.glfwGetMouseButton(this.client.getWindow().getHandle(), GLFW.GLFW_MOUSE_BUTTON_LEFT) == GLFW.GLFW_PRESS) { - tapClicked = true; - tapClickTime = Util.getMeasuringTimeMs(); - } - - if (tapClicked) { - long clickTimePassed = Util.getMeasuringTimeMs() - tapClickTime; - - if (clickTimePassed >= CLICK_FADE_DURATION) { - // After fade out, close splash screen - try { - this.client.setOverlay(null); - this.exceptionHandler.accept(Optional.empty()); - } catch (Exception ignored) {} - this.soar_animationStartTime = -1L; - this.welcomeDisplayed = false; - this.tapPromptDisplayed = false; - this.tapClicked = false; - this.welcomeStartTime = -1L; - this.tapPromptStartTime = -1L; - this.tapClickTime = -1L; - return; - } - - renderWelcomeScreen(width, height, welcomeTimePassed, true, clickTimePassed); - return; - } - - // Check if timeout (auto exit after display time) - if (welcomeTimePassed >= WELCOME_DISPLAY_TIME) { - try { - this.client.setOverlay(null); - this.exceptionHandler.accept(Optional.empty()); - } catch (Exception ignored) {} - this.soar_animationStartTime = -1L; - this.welcomeDisplayed = false; - this.tapPromptDisplayed = false; - this.tapClicked = false; - this.welcomeStartTime = -1L; - this.tapPromptStartTime = -1L; - this.tapClickTime = -1L; - return; - } - - renderWelcomeScreen(width, height, welcomeTimePassed, false, 0); - return; - } - - // Normal loading animation - float alpha = 1f; - long fadeStartTime = ANIMATION_TOTAL_TIME - FADE_DURATION; - if (timePassed > fadeStartTime) { - long fadeTimePassed = timePassed - fadeStartTime; - alpha = 1f - (float)fadeTimePassed / FADE_DURATION; - } - alpha = Math.max(0f, alpha); - - renderLoadingScreen(width, height, timePassed, alpha, true); - } - - @Unique - private boolean isTapPromptClicked(int width, int height, int mouseX, int mouseY) { - // Calculate tap prompt text position and size - String tapText = "Tap to start"; - Font tapFont = Fonts.getMedium(24f); - Rect tapBounds = tapFont.measureText(tapText); - - float tapX = (width - tapBounds.getWidth()) / 2; - float tapY = height / 2f + 15; // Adjusted to height/2 + 15 - - // Check if mouse is within text area (with padding) - float padding = 15f; - return mouseX >= tapX - padding && - mouseX <= tapX + tapBounds.getWidth() + padding && - mouseY >= tapY - padding && - mouseY <= tapY + tapBounds.getHeight() + padding; - } - - @Unique - private void renderLoadingScreen(int width, int height, long timePassed, float alpha, boolean showProgress) { - // Background - Skia.drawRect(0, 0, width, height, new Color(0, 0, 0, (int)(255 * alpha))); - - // Calculate scaled logo size and position - int scaledSize = (int)(LOGO_ACTUAL_SIZE * LOGO_SCALE); - int logoX = (width - scaledSize) / 2; - int logoY = (height - scaledSize) / 3; - - // Draw logo - drawLogo(logoX, logoY, scaledSize, alpha); - - if (showProgress) { - // Progress bar - float progress = Math.min(1f, (float) timePassed / ANIMATION_TOTAL_TIME); - drawProgressBar(width, height, progress, alpha); - } else { - // Reloading progress bar - drawReloadingProgressBar(width, height, timePassed, alpha); - } - } - - @Unique - private void drawLogo(int x, int y, int size, float alpha) { - // Draw logo using Skia - int textureId = MinecraftClient.getInstance().getTextureManager().getTexture(CUSTOM_LOGO).getGlId(); - Skia.drawImage(textureId, x, y, size, size, alpha); - } - - @Unique - private void drawProgressBar(int width, int height, float progress, float alpha) { - int barWidth = width / 2; - int barHeight = PROGRESS_BAR_HEIGHT; - int barX = (width - barWidth) / 2; - int barY = height - 200; - - // Progress bar background - Skia.drawRect(barX, barY, barWidth, barHeight, - new Color(0x30, 0x30, 0x30, (int)(255 * alpha))); - - // Progress bar foreground - int progressWidth = (int)(barWidth * progress); - Skia.drawRect(barX, barY, progressWidth, barHeight, - new Color(255, 255, 255, (int)(255 * alpha))); - } - - @Unique - private void drawReloadingProgressBar(int width, int height, long time, float alpha) { - int barWidth = width / 2; - int barHeight = PROGRESS_BAR_HEIGHT; - int barX = (width - barWidth) / 2; - int barY = height - 200; - - // Progress bar background - Skia.drawRect(barX, barY, barWidth, barHeight, - new Color(0x30, 0x30, 0x30, (int)(255 * alpha))); - - // Dynamic progress indicator - long cycle = 1500L; - float p = (float)(time % cycle) / (float)cycle; - int indicatorWidth = barWidth / 4; - int start = (int)((barWidth + indicatorWidth) * p) - indicatorWidth; - int end = Math.min(start + indicatorWidth, barWidth); - - Skia.drawRect(barX + Math.max(0, start), barY, - barX + end, barHeight, - new Color(255, 255, 255, (int)(255 * alpha))); - } - - @Unique - private void renderWelcomeScreen(int width, int height, long welcomeTimePassed, boolean clicked, long clickTimePassed) { - // Background (always full opacity) - Skia.drawRect(0, 0, width, height, new Color(0, 0, 0, 255)); - - // Text transparency calculations - float welcomeAlpha = 1.0f; // Welcome text always full opacity (no animation) - float ttsAlpha = 1.0f; // TTS text alpha - - if (clicked) { - // After click: 2-second fade out for all text - float clickFadeAlpha = 1f - (float)clickTimePassed / CLICK_FADE_DURATION; - welcomeAlpha = Math.max(0f, clickFadeAlpha); - ttsAlpha = Math.max(0f, clickFadeAlpha); - } else { - // Before click: TTS text has continuous fade in/out animation - if (tapPromptDisplayed) { - long ttsTimePassed = Util.getMeasuringTimeMs() - tapPromptStartTime; - ttsAlpha = getTTSAnimationAlpha(ttsTimePassed); - } else { - ttsAlpha = 0f; // Not displayed yet - } - // Welcome text remains at full opacity - welcomeAlpha = 1.0f; - } - - // Draw welcome text (no animation, just fade out after click) - String welcomeText = "Welcome to Pupper Client"; - Font welcomeFont = Fonts.getMedium(32f); - - // Calculate text position (centered) - Rect welcomeBounds = welcomeFont.measureText(welcomeText); - float welcomeX = (width - welcomeBounds.getWidth()) / 2; - float welcomeY = height / 2f - welcomeBounds.getHeight() / 2; - - // Draw welcome text (with transparency only after click) - Color welcomeColor = new Color(1.0f, 1.0f, 1.0f, welcomeAlpha); - Skia.drawText(welcomeText, welcomeX, welcomeY, welcomeColor, welcomeFont); - - // Draw TTS text (if displayed) - if (tapPromptDisplayed) { - String ttsText = "Tap to start"; - Font ttsFont = Fonts.getMedium(24f); - - // Calculate text position (height/2 + 15) - Rect ttsBounds = ttsFont.measureText(ttsText); - float ttsX = (width - ttsBounds.getWidth()) / 2; - float ttsY = height / 2f + 180; - - // Draw subtle white shadow for TTS text (very light shadow) - if (ttsAlpha > 0) { - // White shadow with reduced opacity and smaller offset - float shadowOpacity = ttsAlpha * 0.3f; // Very subtle shadow - Color shadowColor = new Color(1.0f, 1.0f, 1.0f, shadowOpacity); - - // Very small offset for subtle shadow - float shadowOffset = 0.7f; - - // Draw just one offset shadow for subtle effect - Skia.drawText(ttsText, ttsX + shadowOffset, ttsY, shadowColor, ttsFont); - - // Optional: draw a second layer with even smaller offset for smoother shadow - float shadowOffset2 = 0.3f; - Skia.drawText(ttsText, ttsX + shadowOffset2, ttsY, shadowColor, ttsFont); - } - - // Draw TTS text main layer - // Use white color for main text to contrast with black background - Color ttsColor = new Color(1.0f, 1.0f, 1.0f, ttsAlpha); - Skia.drawText(ttsText, ttsX, ttsY, ttsColor, ttsFont); - } - } - - @Unique - private static float getTTSAnimationAlpha(long ttsTimePassed) { - // Calculate pulse animation: fade in and out, 2-second cycle - long cycle = TTS_CYCLE_DURATION; - float timeInCycle = ttsTimePassed % cycle; - - // Use sine wave for smooth fade in/out animation - // sin(2π * time / period) mapped to [0.3, 1.0] range - float sinValue = (float) Math.sin(2 * Math.PI * timeInCycle / cycle); - float alpha = 0.65f + 0.35f * sinValue; // Varies between 0.3 and 1.0 - - // Ensure smooth start - float fadeInDuration = 500f; - if (ttsTimePassed < fadeInDuration) { - alpha *= (float)ttsTimePassed / fadeInDuration; - } - - return Math.max(0f, Math.min(1f, alpha)); - } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinTitleScreen.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinTitleScreen.java index f66c398..2d13ab0 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinTitleScreen.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/gui/MixinTitleScreen.java @@ -1,31 +1,27 @@ package cn.pupperclient.mixin.mixins.minecraft.client.gui; -import cn.pupperclient.gui.MainMenuGui; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.network.chat.Component; 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; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.text.Text; - @Mixin(value = TitleScreen.class, priority = 1001) public abstract class MixinTitleScreen extends Screen { - protected MixinTitleScreen(Text title) { + protected MixinTitleScreen(Component title) { super(title); } - @Inject(method = "init()V", at = @At("HEAD"), cancellable = true) + @Inject(method = "init()V", at = @At("HEAD")) public void onInit(CallbackInfo ci) { - MinecraftClient.getInstance().setScreen(new MainMenuGui()); - ci.cancel(); + } - @Inject(method = "render", at = @At("HEAD"), cancellable = true) + @Inject(method = "extractRenderState", at = @At("HEAD")) public void onRender(CallbackInfo ci) { - ci.cancel(); + } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/option/MixinKeyBinding.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/option/MixinKeyBinding.java index e2b5c3d..045e033 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/option/MixinKeyBinding.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/option/MixinKeyBinding.java @@ -10,21 +10,20 @@ import cn.pupperclient.management.mod.impl.player.SnapTapMod; import cn.pupperclient.mixin.interfaces.IMixinKeyBinding; +import com.mojang.blaze3d.platform.InputConstants; +import net.minecraft.client.KeyMapping; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.util.InputUtil; - -@Mixin(KeyBinding.class) +@Mixin(KeyMapping.class) public class MixinKeyBinding implements IMixinKeyBinding { @Shadow @Final - private InputUtil.Key defaultKey; + private InputConstants.Key defaultKey; @Shadow - private boolean pressed; + private boolean isDown; - @Inject(method = "isPressed", at = @At("HEAD"), cancellable = true) + @Inject(method = "isDown", at = @At("HEAD"), cancellable = true) public void onGetPressed(CallbackInfoReturnable cir) { SnapTapMod mod = SnapTapMod.getInstance(); @@ -33,8 +32,8 @@ public void onGetPressed(CallbackInfoReturnable cir) { return; } - if (this.defaultKey.getCode() == InputUtil.GLFW_KEY_A) { - if (this.pressed) { + if (this.defaultKey.getValue() == InputConstants.KEY_A) { + if (this.isDown) { if (mod.getRightPressTime() == 0) { cir.setReturnValue(true); cir.cancel(); @@ -44,8 +43,8 @@ public void onGetPressed(CallbackInfoReturnable cir) { cir.setReturnValue(mod.getRightPressTime() <= mod.getLeftPressTime()); cir.cancel(); } - } else if (this.defaultKey.getCode() == InputUtil.GLFW_KEY_D) { - if (this.pressed) { + } else if (this.defaultKey.getValue() == InputConstants.KEY_D) { + if (this.isDown) { if (mod.getLeftPressTime() == 0) { cir.setReturnValue(true); cir.cancel(); @@ -55,8 +54,8 @@ public void onGetPressed(CallbackInfoReturnable cir) { cir.setReturnValue(mod.getLeftPressTime() <= mod.getRightPressTime()); cir.cancel(); } - } else if (this.defaultKey.getCode() == InputUtil.GLFW_KEY_W) { - if (this.pressed) { + } else if (this.defaultKey.getValue() == InputConstants.KEY_W) { + if (this.isDown) { if (mod.getForwardPressTime() == 0) { cir.setReturnValue(true); cir.cancel(); @@ -66,8 +65,8 @@ public void onGetPressed(CallbackInfoReturnable cir) { cir.setReturnValue(mod.getBackPressTime() <= mod.getForwardPressTime()); cir.cancel(); } - } else if (this.defaultKey.getCode() == InputUtil.GLFW_KEY_S) { - if (this.pressed) { + } else if (this.defaultKey.getValue() == InputConstants.KEY_S) { + if (this.isDown) { if (mod.getBackPressTime() == 0) { cir.setReturnValue(true); cir.cancel(); @@ -80,7 +79,7 @@ public void onGetPressed(CallbackInfoReturnable cir) { } } - @Inject(method = "setPressed", at = @At("HEAD")) + @Inject(method = "setDown", at = @At("HEAD")) public void setPressed(boolean pressed, CallbackInfo ci) { SnapTapMod mod = SnapTapMod.getInstance(); @@ -89,25 +88,25 @@ public void setPressed(boolean pressed, CallbackInfo ci) { return; } - if (this.defaultKey.getCode() == InputUtil.GLFW_KEY_A) { + if (this.defaultKey.getValue() == InputConstants.KEY_A) { if (pressed) { mod.setLeftPressTime(System.currentTimeMillis()); } else { mod.setLeftPressTime(0); } - } else if (this.defaultKey.getCode() == InputUtil.GLFW_KEY_D) { + } else if (this.defaultKey.getValue() == InputConstants.KEY_D) { if (pressed) { mod.setRightPressTime(System.currentTimeMillis()); } else { mod.setRightPressTime(0); } - } else if (this.defaultKey.getCode() == InputUtil.GLFW_KEY_W) { + } else if (this.defaultKey.getValue() == InputConstants.KEY_W) { if (pressed) { mod.setForwardPressTime(System.currentTimeMillis()); } else { mod.setForwardPressTime(0); } - } else if (this.defaultKey.getCode() == InputUtil.GLFW_KEY_S) { + } else if (this.defaultKey.getValue() == InputConstants.KEY_S) { if (pressed) { mod.setBackPressTime(System.currentTimeMillis()); } else { @@ -118,6 +117,6 @@ public void setPressed(boolean pressed, CallbackInfo ci) { @Override public boolean getRealIsPressed() { - return this.pressed; + return this.isDown; } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/BufferRendererAccessor.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/BufferRendererAccessor.java deleted file mode 100644 index 1b90209..0000000 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/BufferRendererAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.pupperclient.mixin.mixins.minecraft.client.render; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import net.minecraft.client.gl.VertexBuffer; -import net.minecraft.client.render.BufferRenderer; - -@Mixin(BufferRenderer.class) -public interface BufferRendererAccessor { - @Accessor("currentVertexBuffer") - static void setCurrentVertexBuffer(VertexBuffer vertexBuffer) { - } -} diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/GuiRendererMixin.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/GuiRendererMixin.java new file mode 100644 index 0000000..9c76714 --- /dev/null +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/GuiRendererMixin.java @@ -0,0 +1,78 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.mixin.mixins.minecraft.client.render; + +import cn.pupperclient.PupperClient; +import cn.pupperclient.mixin.mixins.accessors.GameRendererAccessor; +import cn.pupperclient.utils.minecraft.interfaces.IMinecraft; +import cn.pupperclient.utils.render.PupperGuiRenderer; +import cn.pupperclient.utils.render.RenderUtils; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gui.render.GuiRenderer; +import net.minecraft.client.gui.render.pip.PictureInPictureRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.feature.FeatureRenderDispatcher; +import net.minecraft.client.renderer.fog.FogRenderer; +import net.minecraft.client.renderer.state.gui.GuiRenderState; +import net.minecraft.util.profiling.Profiler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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(GuiRenderer.class) +public abstract class GuiRendererMixin implements IMinecraft { + @Unique + private PupperGuiRenderer guiRenderer; + + @Shadow + public abstract void endFrame(); + + @Unique + private GuiRenderState renderState; + + @Inject(method = "", at = @At("RETURN")) + private void pupper$init(GuiRenderState renderState, MultiBufferSource.BufferSource bufferSource, SubmitNodeCollector submitNodeCollector, FeatureRenderDispatcher featureRenderDispatcher, List> pictureInPictureRenderers, CallbackInfo ci) { + if ((GuiRenderer) (Object) this instanceof PupperGuiRenderer) return; + this.renderState = new GuiRenderState(); + + guiRenderer = new PupperGuiRenderer( + this.renderState, + bufferSource, + submitNodeCollector, + featureRenderDispatcher, + pictureInPictureRenderers + ); + } + + @Inject(method = "draw", at = @At("HEAD")) + private void draw(CallbackInfo ci) { + if (guiRenderer == null) return; + + var fogRenderer = ((GameRendererAccessor) client.gameRenderer).pupper$fogRenderer(); + + if (RenderUtils.canUpdate()) { + Profiler.get().push(PupperClient.getModId() + "_render_2d"); + + RenderUtils.unscaledProjection(); + + guiRenderer.render(fogRenderer.getBuffer(FogRenderer.FogMode.NONE)); + + RenderUtils.scaledProjection(); + + Profiler.get().pop(); + } + + assert client.getMainRenderTarget().getDepthTexture() != null; + RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(client.getMainRenderTarget().getDepthTexture(), 1.0); + endFrame(); + } +} diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/LightmapMixin.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/LightmapMixin.java new file mode 100644 index 0000000..95a6aaa --- /dev/null +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/LightmapMixin.java @@ -0,0 +1,36 @@ +package cn.pupperclient.mixin.mixins.minecraft.client.render; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.GpuTexture; +import net.minecraft.client.renderer.Lightmap; +import net.minecraft.client.renderer.state.LightmapRenderState; +import net.minecraft.util.ARGB; +import net.minecraft.util.profiling.Profiler; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +import cn.pupperclient.management.mod.impl.render.FullbrightMod; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Lightmap.class) +public abstract class LightmapMixin { + @Shadow + @Final + private GpuTexture texture; + + @Inject(method = "render", at = @At("HEAD"), cancellable = true) + private void render$fullbright(LightmapRenderState renderState, CallbackInfo ci) { + if (FullbrightMod.getInstance().isEnabled()) { + var profile = Profiler.get(); + profile.push("lightmap"); + + RenderSystem.getDevice().createCommandEncoder().clearColorTexture(texture, ARGB.color(255, 255, 255, 255)); + + profile.pop(); + ci.cancel(); + } + } +} diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinCamera.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinCamera.java index 29aef97..21b2d08 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinCamera.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinCamera.java @@ -1,5 +1,7 @@ package cn.pupperclient.mixin.mixins.minecraft.client.render; +import cn.pupperclient.management.mod.impl.player.ZoomMod; +import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -9,12 +11,11 @@ import cn.pupperclient.management.mod.impl.player.FreelookMod; import cn.pupperclient.mixin.interfaces.IMixinCameraEntity; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.render.Camera; -import net.minecraft.entity.Entity; -import net.minecraft.world.BlockView; +import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.entity.Entity; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Camera.class) public abstract class MixinCamera { @@ -24,25 +25,32 @@ public abstract class MixinCamera { @Shadow protected abstract void setRotation(float yaw, float pitch); - - @Inject(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setRotation(FF)V", ordinal = 1, shift = At.Shift.AFTER)) - public void lockRotation(BlockView focusedBlock, Entity cameraEntity, boolean isThirdPerson, boolean isFrontFacing, float tickDelta, CallbackInfo ci) { - - MinecraftClient client = MinecraftClient.getInstance(); - - if (FreelookMod.getInstance().isEnabled() && FreelookMod.getInstance().isActive() && cameraEntity instanceof ClientPlayerEntity) { - IMixinCameraEntity cameraOverriddenEntity = (IMixinCameraEntity) cameraEntity; - - if (firstTime && MinecraftClient.getInstance().player != null) { - cameraOverriddenEntity.soarClient_CN$setCameraPitch(client.player.getPitch()); - cameraOverriddenEntity.soarClient_CN$setCameraYaw(client.player.getYaw()); - firstTime = false; - } - this.setRotation(cameraOverriddenEntity.soarClient_CN$getCameraYaw(), cameraOverriddenEntity.soarClient_CN$getCameraPitch()); + @Shadow + private @Nullable Entity entity; + + @Inject(method = "alignWithEntity", at = @At("TAIL")) + private void onAlignWithEntity(float partialTicks, CallbackInfo ci) { + if (!FreelookMod.getInstance().isEnabled() || !FreelookMod.getInstance().isActive()) return; + Entity entity = this.entity; + if (!(entity instanceof LocalPlayer)) return; + + var cameraOverridden = (IMixinCameraEntity) entity; + if (firstTime && Minecraft.getInstance().player != null) { + cameraOverridden.soarClient_CN$setCameraYaw(Minecraft.getInstance().player.getYRot()); + cameraOverridden.soarClient_CN$setCameraPitch(Minecraft.getInstance().player.getXRot()); + firstTime = false; } - if (FreelookMod.getInstance().isEnabled() && !FreelookMod.getInstance().isActive() && cameraEntity instanceof ClientPlayerEntity) { - firstTime = true; + + this.setRotation(cameraOverridden.soarClient_CN$getCameraYaw(), cameraOverridden.soarClient_CN$getCameraPitch()); + } + + @Inject(method = "calculateFov", at = @At("RETURN"), cancellable = true) + private void onCalculateFov(float partialTicks, CallbackInfoReturnable cir) { + if (ZoomMod.getInstance().isEnabled()) { + float original = cir.getReturnValue(); + float modified = ZoomMod.getInstance().getFov(original); + cir.setReturnValue(modified); } } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinEntityRenderer.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinEntityRenderer.java index 580609a..40697a4 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinEntityRenderer.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinEntityRenderer.java @@ -1,68 +1,92 @@ package cn.pupperclient.mixin.mixins.minecraft.client.render; import cn.pupperclient.PupperClient; +import cn.pupperclient.PupperLogger; +import cn.pupperclient.management.mod.impl.misc.HypixelMod; +import cn.pupperclient.utils.server.Server; +import cn.pupperclient.utils.server.ServerUtils; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.state.EntityRenderState; +import net.minecraft.client.renderer.state.level.CameraRenderState; +import net.minecraft.network.chat.Component; +import net.minecraft.util.CommonColors; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +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 cn.pupperclient.management.mod.impl.misc.HypixelMod; -import cn.pupperclient.utils.server.Server; -import cn.pupperclient.utils.server.ServerUtils; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.EntityRenderer; -import net.minecraft.client.render.entity.state.EntityRenderState; -import net.minecraft.client.render.entity.state.PlayerEntityRenderState; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; -import net.minecraft.text.Text; -import net.minecraft.util.Colors; -import net.minecraft.util.Formatting; - @Mixin(EntityRenderer.class) public abstract class MixinEntityRenderer { + @Unique + private Entity entity; - @Shadow - @Final - private TextRenderer textRenderer; - - @Inject(method = "renderLabelIfPresent", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/TextRenderer;draw(Lnet/minecraft/text/Text;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/render/VertexConsumerProvider;Lnet/minecraft/client/font/TextRenderer$TextLayerType;II)I", ordinal = 1)) - private void onRenderLevelHead(S inState, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, - int light, CallbackInfo ci) { - - MinecraftClient client = MinecraftClient.getInstance(); + @Shadow + @Final + private Font font; - if (inState instanceof PlayerEntityRenderState state) { - if (ServerUtils.isJoin(Server.HYPIXEL)) { + @Inject(method = "extractRenderState", at = @At(value = "TAIL")) + private void getEntity(T entity, S state, float partialTicks, CallbackInfo ci) { + this.entity = entity; + } - AbstractClientPlayerEntity player = (AbstractClientPlayerEntity) client.world.getEntityById(state.id); + @Inject( + method = "submitNameDisplay(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/level/CameraRenderState;I)V", + at = @At( + value = "INVOKE", + target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V", + shift = At.Shift.AFTER + ) + ) + private void onRenderLevelHead(S state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState camera, int offset, CallbackInfo ci) { + Minecraft client = Minecraft.getInstance(); + if (client.level == null) return; - if (player != null && text.getString().contains(player.getName().getString())) { + if (!ServerUtils.isJoin(Server.HYPIXEL)) return; + if (!HypixelMod.getInstance().isEnabled() || !HypixelMod.getInstance().getLevelHeadSetting().isEnabled()) return; + if (state.entityType != EntityType.PLAYER) return; + if (state.nameTag == null) return; - if (HypixelMod.getInstance().isEnabled() - && HypixelMod.getInstance().getLevelHeadSetting().isEnabled()) { - String levelText = Formatting.AQUA.toString() + "Level: " + Formatting.YELLOW.toString() - + PupperClient.getInstance().getHypixelManager() - .getByUuid(player.getUuid().toString().replace("-", "")).getNetworkLevel(); + AbstractClientPlayer player = (AbstractClientPlayer) entity; + if (player == null) return; - float x = -textRenderer.getWidth(levelText) / 2F; - float y = text.getString().contains("deadmau5") ? -20 : -10; - int color = (int) (client.options.getTextBackgroundOpacity(0.25F) * 255.0F) << 24; + String levelText = ChatFormatting.AQUA + "Level: " + ChatFormatting.YELLOW + + PupperClient.getInstance().getHypixelManager() + .getByUuid(player.getUUID().toString().replace("-", "")) + .getNetworkLevel(); - Matrix4f matrix4f = matrices.peek().getPositionMatrix(); + float x = -font.width(levelText) / 2.0F; + float y = -10.0F; + int backgroundColor = (int) (client.options.getBackgroundOpacity(0.25F) * 255.0F) << 24; + Matrix4f matrix = poseStack.last().pose(); + int light = state.lightCoords; - textRenderer.draw(levelText, x, y, Colors.WHITE, false, matrix4f, vertexConsumers, - TextRenderer.TextLayerType.NORMAL, color, light); - } - } - } - } - } + if (submitNodeCollector instanceof MultiBufferSource bufferSource) { + font.drawInBatch( + Component.literal(levelText), + x, y, + CommonColors.WHITE, + false, + matrix, + bufferSource, + Font.DisplayMode.NORMAL, + backgroundColor, + light + ); + } else { + PupperLogger.warn("MixinEntityRenderer", "submitNodeCollector cast MultiBufferSource error"); + } + } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinGameRenderer.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinGameRenderer.java index 6e86548..b98f81d 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinGameRenderer.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinGameRenderer.java @@ -1,66 +1,19 @@ package cn.pupperclient.mixin.mixins.minecraft.client.render; import cn.pupperclient.management.mod.impl.render.NoHurtFov; -import cn.pupperclient.shader.impl.Kawaseblur; 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; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import cn.pupperclient.event.EventBus; -import cn.pupperclient.event.client.RenderSkiaEvent; -import cn.pupperclient.management.mod.impl.player.ZoomMod; -import cn.pupperclient.management.mod.impl.settings.HUDModSettings; -import cn.pupperclient.management.mod.impl.settings.ModMenuSettings; -import cn.pupperclient.skia.Skia; -import cn.pupperclient.skia.context.SkiaContext; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.Camera; -import net.minecraft.client.render.GameRenderer; -import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.client.renderer.GameRenderer; @Mixin(GameRenderer.class) public class MixinGameRenderer { - - @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;render(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/client/render/RenderTickCounter;)V", shift = At.Shift.BEFORE)) - public void render(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) { - - if (HUDModSettings.getInstance().getBlurSetting().isEnabled()) { - Kawaseblur.INGAME_BLUR.draw((int) HUDModSettings.getInstance().getBlurIntensitySetting().getValue()); - } - - SkiaContext.draw((context) -> { - Skia.save(); - Skia.scale((float) MinecraftClient.getInstance().getWindow().getScaleFactor()); - EventBus.getInstance().post(new RenderSkiaEvent(context)); - Skia.restore(); - }); - } - - @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;render(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/client/render/RenderTickCounter;)V", shift = At.Shift.AFTER)) - public void renderGuiBlur(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) { - - if (HUDModSettings.getInstance().getBlurSetting().isEnabled()) { - Kawaseblur.GUI_BLUR.draw((int) ModMenuSettings.getInstance().getBlurIntensitySetting().getValue()); - } - } - - @Inject(method = "getFov", at = @At(value = "RETURN", ordinal = 1), cancellable = true) - private void getFov(Camera camera, float tickDelta, boolean changingFov, CallbackInfoReturnable cir) { - if (ZoomMod.getInstance().isEnabled()) { - float value = cir.getReturnValue(); - value = ZoomMod.getInstance().getFov(value); - cir.setReturnValue(value); - } - } - - @Inject(method = "tiltViewWhenHurt", at = @At("HEAD"), cancellable = true) + @Inject(method = "bobHurt", at = @At("HEAD"), cancellable = true) private void tiltViewWhenHurt(CallbackInfo ci) { if (NoHurtFov.getInstance().isEnabled() && NoHurtFov.getInstance().nohurtFov.isEnabled()) { ci.cancel(); } } - } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinHeldItemRenderer.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinHeldItemRenderer.java index d7ebc44..b520eaf 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinHeldItemRenderer.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinHeldItemRenderer.java @@ -1,5 +1,6 @@ package cn.pupperclient.mixin.mixins.minecraft.client.render; +import net.minecraft.client.renderer.SubmitNodeCollector; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -9,79 +10,65 @@ import cn.pupperclient.management.mod.impl.player.OldAnimationsMod; import cn.pupperclient.management.mod.impl.render.CustomHandMod; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.ItemInHandRenderer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.item.BowItem; +import net.minecraft.world.item.FishingRodItem; +import net.minecraft.world.item.ItemStack; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.item.HeldItemRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.BowItem; -import net.minecraft.item.FishingRodItem; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Arm; -import net.minecraft.util.Hand; - -@Mixin(HeldItemRenderer.class) +@Mixin(ItemInHandRenderer.class) public abstract class MixinHeldItemRenderer { @Shadow - protected abstract void applySwingOffset(MatrixStack matrices, Arm arm, float swingProgress); - - @Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = ("Lnet/minecraft/client/render/item/HeldItemRenderer;renderItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V"), ordinal = 1)) - private void renderFirstPersonItem(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, - float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, - VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { + protected abstract void applyItemArmAttackTransform(PoseStack matrices, HumanoidArm arm, float swingProgress); + @Inject(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;I)V", ordinal = 1)) + private void renderFirstPersonItem(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack item, float inverseArmHeight, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) { OldAnimationsMod mod = OldAnimationsMod.getInstance(); if (item.getItem() instanceof BowItem && mod.isEnabled() && mod.isOldBow()) { - matrices.translate(0f, 0.05f, 0.04f); - matrices.scale(0.93f, 1f, 1f); + poseStack.translate(0f, 0.05f, 0.04f); + poseStack.scale(0.93f, 1f, 1f); } else if (item.getItem() instanceof FishingRodItem && mod.isEnabled() && mod.isOldRod()) { - matrices.translate(0.08f, -0.027f, -0.33f); - matrices.scale(0.93f, 1f, 1f); + poseStack.translate(0.08f, -0.027f, -0.33f); + poseStack.scale(0.93f, 1f, 1f); } } - @Inject(method = "renderFirstPersonItem", at = @At("HEAD")) - private void applyCustomHand(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, - float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, - VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { - + @Inject(method = "renderArmWithItem", at = @At("HEAD")) + private void applyCustomHand(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) { CustomHandMod mod = CustomHandMod.getInstance(); if(mod.isEnabled()) { - matrices.translate(mod.getX(), mod.getY(), mod.getZ()); - matrices.scale(mod.getScale(), mod.getScale(), mod.getScale()); + poseStack.translate(mod.getX(), mod.getY(), mod.getZ()); + poseStack.scale(mod.getScale(), mod.getScale(), mod.getScale()); } } - @Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;applyEquipOffset(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/util/Arm;F)V", ordinal = 2, shift = At.Shift.AFTER)) - private void applyFoodSwingOffset(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, - float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, - VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { - applyOldSwingOffset(player, hand, swingProgress, matrices); + @Inject(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;applyItemArmTransform(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/entity/HumanoidArm;F)V", ordinal = 2, shift = At.Shift.AFTER)) + private void applyFoodSwingOffset(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) { + applyOldSwingOffset(player, hand, attack, poseStack); } - @Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;applyEquipOffset(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/util/Arm;F)V", ordinal = 3, shift = At.Shift.AFTER)) - private void applyBlockingSwingOffset(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, - float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, - VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { - applyOldSwingOffset(player, hand, swingProgress, matrices); + @Inject(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;applyItemArmTransform(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/entity/HumanoidArm;F)V", ordinal = 3, shift = At.Shift.AFTER)) + private void applyBlockingSwingOffset(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) { + applyOldSwingOffset(player, hand, attack, poseStack); } - @Inject(method = "renderFirstPersonItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;applyEquipOffset(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/util/Arm;F)V", ordinal = 4, shift = At.Shift.AFTER)) - private void applyBowSwingOffset(AbstractClientPlayerEntity player, float tickDelta, float pitch, Hand hand, - float swingProgress, ItemStack item, float equipProgress, MatrixStack matrices, - VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { - applyOldSwingOffset(player, hand, swingProgress, matrices); + @Inject(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;applyItemArmTransform(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/entity/HumanoidArm;F)V", ordinal = 4, shift = At.Shift.AFTER)) + private void applyBowSwingOffset(AbstractClientPlayer player, float frameInterp, float xRot, InteractionHand hand, float attack, ItemStack itemStack, float inverseArmHeight, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords, CallbackInfo ci) { + applyOldSwingOffset(player, hand, attack, poseStack); } @Unique - private void applyOldSwingOffset(AbstractClientPlayerEntity player, Hand hand, float swingProgress, - MatrixStack matrices) { + private void applyOldSwingOffset(AbstractClientPlayer player, InteractionHand hand, float swingProgress, + PoseStack matrices) { if (OldAnimationsMod.getInstance().isEnabled() && OldAnimationsMod.getInstance().isOldBreaking()) { - final Arm arm = hand == Hand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite(); - applySwingOffset(matrices, arm, swingProgress); + final HumanoidArm arm = hand == InteractionHand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite(); + applyItemArmAttackTransform(matrices, arm, swingProgress); } } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinInGameHud.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinInGameHud.java index eda3ab8..17ae541 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinInGameHud.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinInGameHud.java @@ -1,5 +1,10 @@ package cn.pupperclient.mixin.mixins.minecraft.client.render; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.client.renderer.rendertype.RenderType; +import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -8,28 +13,23 @@ import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.RenderGameOverlayEvent; import cn.pupperclient.management.mod.impl.player.OldAnimationsMod; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.hud.InGameHud; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.RenderTickCounter; - -@Mixin(InGameHud.class) +@Mixin(Gui.class) public class MixinInGameHud { - /** - * @author EldoDebug - * @reason drawHeart - */ - @Overwrite - private void drawHeart(DrawContext context, InGameHud.HeartType type, int x, int y, boolean hardcore, boolean blinking, boolean half) { - - OldAnimationsMod mod = OldAnimationsMod.getInstance(); - - context.drawGuiTexture(RenderLayer::getGuiTextured, type.getTexture(hardcore, half, (!mod.isEnabled() || !mod.isDisableHeartFlash()) && blinking), x, y, 9, 9); - } +// /** +// * @author EldoDebug +// * @reason drawHeart +// */ +// @Overwrite +// private void extractHeart(final GuiGraphicsExtractor graphics, final Gui.HeartType type, final int xo, final int yo, final boolean isHardcore, final boolean blinks, final boolean half) { +// // OldAnimationsMod mod = OldAnimationsMod.getInstance(); +// // graphics.blitSprite(RenderPipelines.GUI, type.getSprite(isHardcore, half, (!mod.isEnabled() || !mod.isDisableHeartFlash()) && blinks), xo, yo, 9, 9); +// } - @Inject(method = "renderMainHud", at = @At("TAIL")) - private void renderMainHud(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { + @Inject(method = "extractHotbarAndDecorations", at = @At("TAIL")) + private void renderMainHud(GuiGraphicsExtractor context, DeltaTracker tickCounter, CallbackInfo ci) { EventBus.getInstance().post(new RenderGameOverlayEvent(context)); } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinInGameOverlayRenderer.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinInGameOverlayRenderer.java index ad56a27..601fe85 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinInGameOverlayRenderer.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinInGameOverlayRenderer.java @@ -1,32 +1,31 @@ package cn.pupperclient.mixin.mixins.minecraft.client.render; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; 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; import cn.pupperclient.management.mod.impl.render.OverlayEditorMod; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.ScreenEffectRenderer; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.hud.InGameOverlayRenderer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.util.math.MatrixStack; - -@Mixin(InGameOverlayRenderer.class) +@Mixin(ScreenEffectRenderer.class) public class MixinInGameOverlayRenderer { - @Inject(method = "renderUnderwaterOverlay", at = @At("HEAD"), cancellable = true) - private static void renderUnderwaterOverlay(MinecraftClient client, MatrixStack matrices, - VertexConsumerProvider vertexConsumers, CallbackInfo ci) { + @Inject(method = "renderWater", at = @At("HEAD"), cancellable = true) + private static void renderUnderwaterOverlay(Minecraft client, PoseStack matrices, + MultiBufferSource vertexConsumers, CallbackInfo ci) { if (OverlayEditorMod.getInstance().isEnabled() && OverlayEditorMod.getInstance().isClearWater()) { ci.cancel(); } } - @Inject(method = "renderFireOverlay", at = @At("HEAD"), cancellable = true) - private static void renderFireOverlay(MatrixStack matrices, VertexConsumerProvider vertexConsumers, - CallbackInfo ci) { + @Inject(method = "renderFire", at = @At("HEAD"), cancellable = true) + private static void renderFireOverlay(PoseStack poseStack, MultiBufferSource bufferSource, TextureAtlasSprite sprite, CallbackInfo ci) { if (OverlayEditorMod.getInstance().isEnabled() && OverlayEditorMod.getInstance().isClearFire()) { ci.cancel(); diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinLightmapTextureManager.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinLightmapTextureManager.java deleted file mode 100644 index 254342e..0000000 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/MixinLightmapTextureManager.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.pupperclient.mixin.mixins.minecraft.client.render; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import cn.pupperclient.management.mod.impl.render.FullbrightMod; - -import net.minecraft.client.render.LightmapTextureManager; - -@Mixin(LightmapTextureManager.class) -public class MixinLightmapTextureManager { - - @ModifyExpressionValue(method = "update(F)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/SimpleOption;getValue()Ljava/lang/Object;", ordinal = 1)) - private Object injectFullBright(Object original) { - if (FullbrightMod.getInstance().isEnabled()) { - return (double) FullbrightMod.getInstance().getGamma(); - } - return original; - } -} diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/PupperInGameHud.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/PupperInGameHud.java index 2613860..d8af8c9 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/PupperInGameHud.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/PupperInGameHud.java @@ -1,210 +1,22 @@ package cn.pupperclient.mixin.mixins.minecraft.client.render; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.hud.InGameHud; -import net.minecraft.client.option.AttackIndicator; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.RenderTickCounter; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Arm; -import org.spongepowered.asm.mixin.Final; +import cn.pupperclient.event.EventBus; +import cn.pupperclient.event.client.DrawItemHotbarEvent; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiGraphicsExtractor; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -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; -@Mixin(InGameHud.class) +@Mixin(Gui.class) public class PupperInGameHud { - @Shadow @Final private MinecraftClient client; + @Inject(method = "extractItemHotbar", at = @At("HEAD"), cancellable = true) + private void HotbarRender(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker, CallbackInfo ci) { + DrawItemHotbarEvent event = new DrawItemHotbarEvent(); + EventBus.getInstance().post(event); - @Shadow - private PlayerEntity getCameraPlayer() { - Entity var2 = this.client.getCameraEntity(); - PlayerEntity var10000; - if (var2 instanceof PlayerEntity playerEntity) { - var10000 = playerEntity; - } else { - var10000 = null; - } - return var10000; - } - - @Unique private long lastHotbarUpdate = 0; - @Unique private int lastSelectedSlot = 0; - @Unique private float slotAnimationProgress = 0f; - @Unique private float offhandAlpha = 0f; - - @Inject(method = "renderHotbar", at = @At("HEAD"), cancellable = true) - private void replaceHotbarRender(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { - ci.cancel(); // 取消原版物品栏绘制 - drawCustomHotbar(context, tickCounter); - } - - @Unique - private void drawCustomHotbar(DrawContext context, RenderTickCounter tickCounter) { - PlayerEntity playerEntity = this.getCameraPlayer(); - if (playerEntity == null) return; - - ItemStack itemStack = playerEntity.getOffHandStack(); - Arm arm = playerEntity.getMainArm().getOpposite(); - int centerX = context.getScaledWindowWidth() / 2; - int hotbarY = context.getScaledWindowHeight() - 22; - - int selectedSlot = playerEntity.getInventory().selectedSlot; - updateSlotAnimation(selectedSlot); - updateOffhandAlpha(playerEntity); - - context.getMatrices().push(); - context.getMatrices().translate(0.0F, 0.0F, -90.0F); - - // 绘制自定义白色背景 - drawCustomHotbarBackground(context, centerX, hotbarY, selectedSlot); - - // 绘制原版选择框 - context.drawGuiTexture(RenderLayer::getGuiTextured, InGameHud.HOTBAR_SELECTION_TEXTURE, - centerX - 91 - 1 + selectedSlot * 20, hotbarY - 1, 24, 23); - - // 绘制副手背景(带透明度) - if (!itemStack.isEmpty() || offhandAlpha > 0) { - drawOffhandBackground(context, centerX, hotbarY, arm, offhandAlpha); - } - - context.getMatrices().pop(); - - // 绘制物品(带动画) - for(int i = 0; i < 9; ++i) { - int slotX = centerX - 90 + i * 20 + 2; - int slotY = context.getScaledWindowHeight() - 16 - 3; - - // 计算动画偏移 - float slotOffset = 0; - if (i == lastSelectedSlot) { - slotOffset = (1 - slotAnimationProgress) * 3; - } else if (i == selectedSlot) { - slotOffset = slotAnimationProgress * 3; - } - - this.renderHotbarItem(context, slotX, (int)(slotY + slotOffset), tickCounter, playerEntity, - playerEntity.getInventory().main.get(i), i + 1); - } - - // 绘制副手物品(带透明度) - if (!itemStack.isEmpty() && offhandAlpha > 0) { - int offhandY = context.getScaledWindowHeight() - 16 - 3; - if (arm == Arm.LEFT) { - this.renderHotbarItem(context, centerX - 91 - 26, offhandY, tickCounter, playerEntity, itemStack, 100); - } else { - this.renderHotbarItem(context, centerX + 91 + 10, offhandY, tickCounter, playerEntity, itemStack, 100); - } - } - - // 保留原版攻击冷却指示器 - if (this.client.options.getAttackIndicator().getValue() == AttackIndicator.HOTBAR) { - float f = this.client.player.getAttackCooldownProgress(0.0F); - if (f < 1.0F) { - int indicatorY = context.getScaledWindowHeight() - 20; - int indicatorX = centerX + 91 + 6; - if (arm == Arm.RIGHT) { - indicatorX = centerX - 91 - 22; - } - - int progress = (int)(f * 19.0F); - context.drawGuiTexture(RenderLayer::getGuiTextured, InGameHud.HOTBAR_ATTACK_INDICATOR_BACKGROUND_TEXTURE, - indicatorX, indicatorY, 18, 18); - context.drawGuiTexture(RenderLayer::getGuiTextured, InGameHud.HOTBAR_ATTACK_INDICATOR_PROGRESS_TEXTURE, - 18, 18, 0, 18 - progress, indicatorX, indicatorY + 18 - progress, 18, progress); - } - } - } - - @Unique - private void drawCustomHotbarBackground(DrawContext context, int centerX, int hotbarY, int selectedSlot) { - int hotbarWidth = 182; - int hotbarX = centerX - 91; - - // 绘制主背景(白色半透明) - for(int i = 0; i < 9; ++i) { - int slotX = hotbarX + i * 20; - - // 计算动画偏移 - float slotOffset = 0; - if (i == lastSelectedSlot) { - slotOffset = (1 - slotAnimationProgress) * 3; - } else if (i == selectedSlot) { - slotOffset = slotAnimationProgress * 3; - } - - // 槽位背景颜色 - int color = (i == selectedSlot) ? - 0x80FFFFFF : // 选中槽位更亮 - 0x40FFFFFF; // 普通槽位 - - // 绘制槽位背景 - context.fill(slotX + 1, (int)(hotbarY + 1 + slotOffset), - slotX + 19, (int)(hotbarY + 19 + slotOffset), color); - - // 绘制选中指示器 - if (i == selectedSlot) { - context.fill(slotX, (int)(hotbarY - 1 + slotOffset), - slotX + 20, (int)(hotbarY + 1 + slotOffset), 0xE0FFFFFF); - } - } - } - - @Unique - private void drawOffhandBackground(DrawContext context, int centerX, int hotbarY, Arm arm, float alpha) { - int color = (int)(alpha * 64) << 24 | 0xFFFFFF; // 白色带透明度 - - if (arm == Arm.LEFT) { - // 左侧副手背景 - context.fill(centerX - 91 - 29, hotbarY - 1, - centerX - 91, hotbarY + 23, color); - } else { - // 右侧副手背景 - context.fill(centerX + 91, hotbarY - 1, - centerX + 91 + 29, hotbarY + 23, color); - } - } - - @Unique - private void updateSlotAnimation(int currentSlot) { - long currentTime = System.currentTimeMillis(); - - if (currentSlot != lastSelectedSlot) { - lastSelectedSlot = currentSlot; - lastHotbarUpdate = currentTime; - slotAnimationProgress = 0f; - } - - if (slotAnimationProgress < 1f) { - long elapsed = currentTime - lastHotbarUpdate; - slotAnimationProgress = Math.min(elapsed / 200f, 1f); - slotAnimationProgress = easeOutCubic(slotAnimationProgress); - } - } - - @Unique - private void updateOffhandAlpha(PlayerEntity player) { - ItemStack offhandStack = player.getOffHandStack(); - - if (!offhandStack.isEmpty()) { - offhandAlpha = Math.min(offhandAlpha + 0.1f, 1f); - } else { - offhandAlpha = Math.max(offhandAlpha - 0.05f, 0f); - } - } - - @Unique - private float easeOutCubic(float x) { - return (float) (1 - Math.pow(1 - x, 3)); - } - - @Shadow - private void renderHotbarItem(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed) { + if (event.isCancelled()) ci.cancel(); } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/PupperScoreboard.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/PupperScoreboard.java index 6d21c64..9601739 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/PupperScoreboard.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/PupperScoreboard.java @@ -1,15 +1,15 @@ package cn.pupperclient.mixin.mixins.minecraft.client.render; import cn.pupperclient.management.mod.impl.hud.Scoreboard; -import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.gui.Gui; 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(InGameHud.class) +@Mixin(Gui.class) public class PupperScoreboard { - @Inject(method = "renderScoreboardSidebar*", at = @At("HEAD"), cancellable = true) + @Inject(method = "extractScoreboardSidebar*", at = @At("HEAD"), cancellable = true) private void renderCustomScoreboard(CallbackInfo ci) { if (Scoreboard.getInstance().isEnabled()) { ci.cancel(); diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/RenderPipelineMixin.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/RenderPipelineMixin.java new file mode 100644 index 0000000..be24a7f --- /dev/null +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/render/RenderPipelineMixin.java @@ -0,0 +1,26 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.mixin.mixins.minecraft.client.render; + +import cn.pupperclient.mixin.interfaces.IRenderPipeline; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(RenderPipeline.class) +public abstract class RenderPipelineMixin implements IRenderPipeline { + @Unique + private boolean lineSmooth; + + @Override + public void pupper$setLineSmooth(boolean lineSmooth) { + this.lineSmooth = lineSmooth; + } + + @Override + public boolean pupper$getLineSmooth() { + return lineSmooth; + } +} diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/sound/MixinSoundSystem.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/sound/MixinSoundSystem.java index 32b2e0e..28324d8 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/sound/MixinSoundSystem.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/sound/MixinSoundSystem.java @@ -1,37 +1,41 @@ package cn.pupperclient.mixin.mixins.minecraft.client.sound; -import java.util.Arrays; -import java.util.List; - +import cn.pupperclient.management.mod.impl.player.OldAnimationsMod; +import net.minecraft.client.resources.sounds.SoundInstance; +import net.minecraft.client.sounds.SoundEngine; +import net.minecraft.resources.Identifier; +import net.minecraft.sounds.SoundEvents; 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 cn.pupperclient.management.mod.impl.player.OldAnimationsMod; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import net.minecraft.client.sound.SoundInstance; -import net.minecraft.client.sound.SoundSystem; -import net.minecraft.sound.SoundEvents; -import net.minecraft.util.Identifier; +import java.util.Arrays; +import java.util.List; -@Mixin(SoundSystem.class) +@Mixin(SoundEngine.class) public class MixinSoundSystem { - @Unique - private final List newPvPSounds = Arrays.asList(SoundEvents.ENTITY_PLAYER_ATTACK_KNOCKBACK.id(), - SoundEvents.ENTITY_PLAYER_ATTACK_SWEEP.id(), SoundEvents.ENTITY_PLAYER_ATTACK_CRIT.id(), - SoundEvents.ENTITY_PLAYER_ATTACK_STRONG.id(), SoundEvents.ENTITY_PLAYER_ATTACK_WEAK.id(), - SoundEvents.ENTITY_PLAYER_ATTACK_NODAMAGE.id()); - - @Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;)V", at = @At("HEAD"), cancellable = true) - public void oldAnimations$disableNewPvPSounds(SoundInstance sound, CallbackInfo ci) { - - if (OldAnimationsMod.getInstance().isEnabled() && OldAnimationsMod.getInstance().isOldPvPSounds() - && newPvPSounds.contains(sound.getId())) { - ci.cancel(); - return; - } - } + @Unique + private final List newPvPSounds = Arrays.asList( + SoundEvents.PLAYER_ATTACK_KNOCKBACK.location(), + SoundEvents.PLAYER_ATTACK_SWEEP.location(), + SoundEvents.PLAYER_ATTACK_CRIT.location(), + SoundEvents.PLAYER_ATTACK_STRONG.location(), + SoundEvents.PLAYER_ATTACK_WEAK.location(), + SoundEvents.PLAYER_ATTACK_NODAMAGE.location() + ); + + @Inject( + method = "play(Lnet/minecraft/client/resources/sounds/SoundInstance;)Lnet/minecraft/client/sounds/SoundEngine$PlayResult;", + at = @At("HEAD"), + cancellable = true + ) + public void oldAnimations$disableNewPvPSounds(SoundInstance sound, CallbackInfoReturnable cir) { + if (OldAnimationsMod.getInstance().isEnabled() && OldAnimationsMod.getInstance().isOldPvPSounds() + && newPvPSounds.contains(sound.getIdentifier())) { + cir.setReturnValue(SoundEngine.PlayResult.NOT_STARTED); + } + } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/util/MixinWindow.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/util/MixinWindow.java index c5637d3..7ec8305 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/util/MixinWindow.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/client/util/MixinWindow.java @@ -1,14 +1,15 @@ package cn.pupperclient.mixin.mixins.minecraft.client.util; import cn.pupperclient.PupperClient; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import cn.pupperclient.skia.context.SkiaContext; - -import net.minecraft.client.util.Window; +import com.mojang.blaze3d.platform.Window; import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFWImage; import org.lwjgl.stb.STBImage; @@ -21,19 +22,18 @@ @Mixin(Window.class) public class MixinWindow { + @Shadow + @Final + private long handle; - @Inject(method = "onFramebufferSizeChanged", at = @At("RETURN")) + @Inject(method = "onFramebufferResize", at = @At("RETURN")) private void onFramebufferSizeChanged(long window, int width, int height, CallbackInfo ci) { - SkiaContext.createSurface(width, height); + SkiaContext.createSurface(width > 0 ? width : 1, height > 0 ? height : 1, null); } @Inject(method = "", at = @At("RETURN")) private void onWindowInit(CallbackInfo ci) { try { - // 获取窗口句柄 - long handle = ((Window)(Object)this).getHandle(); - - // 从资源加载图标 try (InputStream is = getClass().getResourceAsStream("/assets/pupper/logo.png")) { if (is == null) { System.err.println("PupperClient icon not found!"); diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinAbstractClientPlayerEntity.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinAbstractClientPlayerEntity.java index a324762..7c5216b 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinAbstractClientPlayerEntity.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinAbstractClientPlayerEntity.java @@ -2,45 +2,36 @@ import cn.pupperclient.PupperClient; import com.mojang.authlib.GameProfile; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.util.SkinTextures; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.data.TrackedData; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerModelPart; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Final; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.PlayerModelPart; +import net.minecraft.world.entity.player.PlayerSkin; +import net.minecraft.world.level.Level; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; 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.CallbackInfoReturnable; -@Mixin(value = AbstractClientPlayerEntity.class, priority = 2000) -public abstract class MixinAbstractClientPlayerEntity extends PlayerEntity { - - @Shadow @Final public ClientWorld clientWorld; - +@Mixin(value = AbstractClientPlayer.class, priority = 2000) +public abstract class MixinAbstractClientPlayerEntity extends Player { @Unique private boolean shownCape = false; - public MixinAbstractClientPlayerEntity(World world, BlockPos pos, float yaw, GameProfile gameProfile) { - super(world, pos, yaw, gameProfile); + public MixinAbstractClientPlayerEntity(Level world, GameProfile gameProfile) { + super(world, gameProfile); } - @Inject(method = "getSkinTextures", at = @At("RETURN"), cancellable = true) - public void getSkinTextures(CallbackInfoReturnable cir) { - Identifier customCape = PupperClient.getInstance().getCapeManager().getSelectedCapeTexture(); + @Inject(method = "getSkin", at = @At("RETURN"), cancellable = true) + public void getSkinTextures(CallbackInfoReturnable cir) { + var customCape = PupperClient.getInstance().getCapeManager().getSelectedCapeTexture(); if (customCape != null) { - SkinTextures current = cir.getReturnValue(); - cir.setReturnValue(new SkinTextures( - current.texture(), - current.textureUrl(), + PlayerSkin current = cir.getReturnValue(); + cir.setReturnValue(new PlayerSkin( + current.body(), customCape, - current.elytraTexture(), + current.elytra(), current.model(), current.secure() )); @@ -48,10 +39,10 @@ public void getSkinTextures(CallbackInfoReturnable cir) { } @Override - public void onTrackedDataSet(TrackedData data) { - super.onTrackedDataSet(data); - if (PLAYER_MODEL_PARTS.equals(data)) { - boolean showCape = isPartVisible(PlayerModelPart.CAPE); + public void onSyncedDataUpdated(EntityDataAccessor data) { + super.onSyncedDataUpdated(data); + if (DATA_PLAYER_MODE_CUSTOMISATION.equals(data)) { + boolean showCape = isModelPartShown(PlayerModelPart.CAPE); if (showCape != shownCape) { shownCape = showCape; } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinAvatar.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinAvatar.java new file mode 100644 index 0000000..fe5c66a --- /dev/null +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinAvatar.java @@ -0,0 +1,25 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.mixin.mixins.minecraft.entity; + +import cn.pupperclient.management.mod.impl.player.ForceMainHandMod; +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.Avatar; +import net.minecraft.world.entity.HumanoidArm; +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.CallbackInfoReturnable; + +@Mixin(Avatar.class) +public class MixinAvatar { + @Inject(method = "getMainArm", at = @At("HEAD"), cancellable = true) + private void forceLeftHand(CallbackInfoReturnable cir) { + var self = (Object) this; + if (self != Minecraft.getInstance().player) { + cir.setReturnValue(ForceMainHandMod.getInstance().isRightHand() ? HumanoidArm.RIGHT : HumanoidArm.LEFT); + } + } +} diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinEntity.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinEntity.java index f4d8578..1325ccf 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinEntity.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinEntity.java @@ -1,9 +1,10 @@ package cn.pupperclient.mixin.mixins.minecraft.entity; import cn.pupperclient.utils.misc.SoundEventHelper; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.math.Vec3d; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -16,15 +17,8 @@ import cn.pupperclient.management.mod.impl.player.FreelookMod; import cn.pupperclient.mixin.interfaces.IMixinCameraEntity; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.MathHelper; - @Mixin(Entity.class) public abstract class MixinEntity implements IMixinCameraEntity { - @Unique - protected Vec3d stuckSpeedMultiplier; - @Unique private float cameraPitch; @@ -32,54 +26,36 @@ public abstract class MixinEntity implements IMixinCameraEntity { private float cameraYaw; @Shadow - public abstract float getPitch(); + public abstract float getXRot(); @Shadow - public abstract float getYaw(); - - @Shadow - public abstract boolean equals(Object o); - - @Shadow - public abstract float getPitch(float tickDelta); - - @Shadow - public abstract float getYaw(float tickDelta); + public abstract float getYRot(); - @Shadow - public abstract Vec3d getRotationVector(float pitch, float yaw); - - @Shadow - public abstract boolean saveNbt(NbtCompound nbt); - - @Shadow - public abstract int getId(); - - @Inject(method = "changeLookDirection", at = @At("HEAD")) + @Inject(method = "turn", at = @At("HEAD")) private void onPlayerDirectionChange(double cursorDeltaX, double cursorDeltaY, CallbackInfo ci) { - float prevPitch = getPitch(); - float prevYaw = getYaw(); + float prevPitch = getXRot(); + float prevYaw = getYRot(); float pitch = prevPitch + (float) (cursorDeltaY * .15); float yaw = prevYaw + (float) (cursorDeltaX * .15); - pitch = MathHelper.clamp(pitch, -90.0F, 90.0F); + pitch = Mth.clamp(pitch, -90.0F, 90.0F); EventBus.getInstance().post(new PlayerDirectionChangeEvent(prevPitch, prevYaw, pitch, yaw)); } - @Inject(method = "changeLookDirection", at = @At("HEAD"), cancellable = true) + @Inject(method = "turn", at = @At("HEAD"), cancellable = true) public void changeCameraLookDirection(double xDelta, double yDelta, CallbackInfo ci) { - if (FreelookMod.getInstance().isEnabled() && FreelookMod.getInstance().isActive() - && (Entity) (Object) this instanceof ClientPlayerEntity) { - double pitchDelta = (yDelta * 0.15); - double yawDelta = (xDelta * 0.15); - - this.cameraPitch = MathHelper.clamp(this.cameraPitch + (float) pitchDelta, -90.0f, 90.0f); - this.cameraYaw += (float) yawDelta; + if (FreelookMod.getInstance().isEnabled() && FreelookMod.getInstance().isActive()) { + if ((Entity) (Object) this instanceof LocalPlayer) { + double pitchDelta = (yDelta * 0.15); + double yawDelta = (xDelta * 0.15); - ci.cancel(); + this.cameraPitch = Mth.clamp(this.cameraPitch + (float) pitchDelta, -90.0f, 90.0f); + this.cameraYaw += (float) yawDelta; - } + ci.cancel(); + } + } } @Override @@ -106,7 +82,7 @@ public void changeCameraLookDirection(double xDelta, double yDelta, CallbackInfo this.cameraYaw = yaw; } - @Inject(method = "playSound", at = @At("HEAD")) + @Inject(method = "playSound(Lnet/minecraft/sounds/SoundEvent;FF)V", at = @At("HEAD")) private void onPlaySound(SoundEvent sound, float volume, float pitch, CallbackInfo ci) { SoundEventHelper.lastSoundSource = (Entity) (Object) this; SoundEventHelper.lastSoundEvent = sound; diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinLivingEntity.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinLivingEntity.java index c41445b..b54332c 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinLivingEntity.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinLivingEntity.java @@ -1,9 +1,5 @@ package cn.pupperclient.mixin.mixins.minecraft.entity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.data.DataTracker; -import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -13,78 +9,81 @@ import cn.pupperclient.management.mod.impl.hud.JumpResetIndicatorMod; import cn.pupperclient.management.mod.impl.player.NoJumpDelayMod; import cn.pupperclient.mixin.interfaces.IMixinLivingEntity; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.LivingEntity; -import net.minecraft.util.Hand; +import net.minecraft.client.Minecraft; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; @Mixin(LivingEntity.class) public abstract class MixinLivingEntity extends Entity implements IMixinLivingEntity{ @Shadow - private int jumpingCooldown; + private int noJumpDelay; @Shadow - public int handSwingTicks; + public int swingTime; @Shadow - public boolean handSwinging; + public boolean swinging; @Shadow - public Hand preferredHand; + public InteractionHand swingingArm; - public MixinLivingEntity(EntityType type, World world) { + public MixinLivingEntity(EntityType type, Level world) { super(type, world); } @Shadow - protected abstract int getHandSwingDuration(); + protected abstract int getCurrentSwingDuration(); @Shadow - public abstract void jump(); + public abstract void jumpFromGround(); @Shadow - public abstract float getYaw(float tickDelta); + public abstract float getViewYRot(float tickDelta); @Shadow - protected abstract void initDataTracker(DataTracker.Builder builder); + protected abstract void defineSynchedData(SynchedEntityData.Builder builder); - @Inject(method = "tickMovement", at = @At("HEAD")) + @Inject(method = "aiStep", at = @At("HEAD")) public void onNoJumpDelay(CallbackInfo ci) { if (NoJumpDelayMod.getInstance().isEnabled()) { - jumpingCooldown = 0; + noJumpDelay = 0; } } - @Inject(method = "jump", at = @At("HEAD")) + @Inject(method = "jumpFromGround", at = @At("HEAD")) private void onJump(CallbackInfo info) { JumpResetIndicatorMod mod = JumpResetIndicatorMod.getInstance(); - MinecraftClient client = MinecraftClient.getInstance(); + Minecraft client = Minecraft.getInstance(); if ((Object) this == client.player) { - mod.setJumpAge(client.player.age); + mod.setJumpAge(client.player.tickCount); mod.setLastTime(System.currentTimeMillis()); } } - @Inject(method = "onDamaged", at = @At("HEAD")) + @Inject(method = "handleDamageEvent", at = @At("HEAD")) private void onDamage(CallbackInfo info) { JumpResetIndicatorMod mod = JumpResetIndicatorMod.getInstance(); - MinecraftClient client = MinecraftClient.getInstance(); + Minecraft client = Minecraft.getInstance(); if ((Object) this == client.player) { - mod.setHurtAge(client.player.age); + mod.setHurtAge(client.player.tickCount); } } @Override - public void soarClient_CN$fakeSwingHand(Hand hand) { - if (!this.handSwinging || this.handSwingTicks >= this.getHandSwingDuration() / 2 || this.handSwingTicks < 0) { - this.handSwingTicks = -1; - this.handSwinging = true; - this.preferredHand = hand; + public void soarClient_CN$fakeSwingHand(InteractionHand hand) { + if (!this.swinging || this.swingTime >= this.getCurrentSwingDuration() / 2 || this.swingTime < 0) { + this.swingTime = -1; + this.swinging = true; + this.swingingArm = hand; } } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinPlayerEntity.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinPlayerEntity.java index 7b0949f..09522b6 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinPlayerEntity.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/entity/MixinPlayerEntity.java @@ -5,32 +5,15 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import cn.pupperclient.management.mod.impl.player.ForceMainHandMod; import cn.pupperclient.management.mod.impl.player.OldAnimationsMod; +import net.minecraft.world.entity.player.Player; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Arm; - -@Mixin(PlayerEntity.class) -public class MixinPlayerEntity { - - @Inject(method = "getAttackCooldownProgress", at = @At("HEAD"), cancellable = true) +@Mixin(Player.class) +public abstract class MixinPlayerEntity { + @Inject(method = "getAttackStrengthScale", at = @At("HEAD"), cancellable = true) public void disableCooldown(CallbackInfoReturnable cir) { if (OldAnimationsMod.getInstance().isEnabled() && OldAnimationsMod.getInstance().isDisableAttackCooldown()) { cir.setReturnValue(1F); } } - - @Inject(method = "getMainArm", at = @At("HEAD"), cancellable = true) - private void injectGetMainArm(CallbackInfoReturnable cir) { - - MinecraftClient client = MinecraftClient.getInstance(); - PlayerEntity player = client.player; - PlayerEntity e = ((PlayerEntity) (Object) this); - - if (ForceMainHandMod.getInstance().isEnabled() && e.getId() != player.getId()) { - cir.setReturnValue(ForceMainHandMod.getInstance().isRightHand() ? Arm.RIGHT : Arm.LEFT); - } - } } diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/network/MixinClientConnection.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/network/MixinClientConnection.java index ff83513..7827261 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/network/MixinClientConnection.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/network/MixinClientConnection.java @@ -1,56 +1,57 @@ package cn.pupperclient.mixin.mixins.minecraft.network; -import net.minecraft.network.PacketCallbacks; +import io.netty.channel.ChannelFutureListener; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import cn.pupperclient.event.EventBus; import cn.pupperclient.event.client.ReceivePacketEvent; import cn.pupperclient.event.client.SendPacketEvent; +import net.minecraft.network.Connection; +import net.minecraft.network.PacketListener; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundBundlePacket; +import net.minecraft.server.RunningOnDifferentThreadException; -import net.minecraft.network.ClientConnection; -import net.minecraft.network.OffThreadException; -import net.minecraft.network.listener.PacketListener; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.s2c.play.BundleS2CPacket; - -@Mixin(ClientConnection.class) +@Mixin(Connection.class) public abstract class MixinClientConnection { @Shadow - private static void handlePacket(Packet packet, PacketListener listener) { + private static void genericsFtw(Packet packet, PacketListener listener) { } @Shadow - protected abstract void sendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, boolean flush); + protected abstract void sendPacket(Packet packet, @Nullable ChannelFutureListener listener, boolean flush); - @Inject(method = "send(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/PacketCallbacks;)V", at = @At("HEAD"), cancellable = true) - private void onSendPacket(Packet packet, PacketCallbacks callbacks, CallbackInfo ci) { + @Redirect( + method = "send(Lnet/minecraft/network/protocol/Packet;Lio/netty/channel/ChannelFutureListener;Z)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;sendPacket(Lnet/minecraft/network/protocol/Packet;Lio/netty/channel/ChannelFutureListener;Z)V") + ) + private void redirectSendPacket(Connection instance, Packet packet, ChannelFutureListener listener, boolean flush) { SendPacketEvent event = new SendPacketEvent(packet); EventBus.getInstance().post(event); - if (event.isCancelled()) { - ci.cancel(); - ClientConnection self = (ClientConnection) (Object) this; - self.send(event.getPacket(), callbacks); - } + if (!event.isCancelled()) { + sendPacket(packet, listener, flush); + } } - @Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true, require = 1) + @Inject(method = "genericsFtw", at = @At("HEAD"), cancellable = true, require = 1) private static void onRecievePacket(Packet packet, PacketListener listener, CallbackInfo ci) { - if (packet instanceof BundleS2CPacket bundleS2CPacket) { + if (packet instanceof ClientboundBundlePacket bundleS2CPacket) { ci.cancel(); - for (Packet packetInBundle : bundleS2CPacket.getPackets()) { + for (Packet packetInBundle : bundleS2CPacket.subPackets()) { try { - handlePacket(packetInBundle, listener); - } catch (OffThreadException ignored) { + genericsFtw(packetInBundle, listener); + } catch (RunningOnDifferentThreadException ignored) { } } return; diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/network/packet/PlayerInteractEntityC2SPacketAccessor.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/network/packet/PlayerInteractEntityC2SPacketAccessor.java deleted file mode 100644 index cc77357..0000000 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/network/packet/PlayerInteractEntityC2SPacketAccessor.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.pupperclient.mixin.mixins.minecraft.network.packet; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; - -@Mixin(PlayerInteractEntityC2SPacket.class) -public interface PlayerInteractEntityC2SPacketAccessor { - - @Accessor("type") - PlayerInteractEntityC2SPacket.InteractTypeHandler getInteractTypeHandler(); - - @Accessor("entityId") - int entityId(); -} diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinBiome.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinBiome.java index 1eaaa1a..554102e 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinBiome.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinBiome.java @@ -6,14 +6,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import cn.pupperclient.management.mod.impl.misc.WeatherChangerMod; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.biome.Biome; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.biome.Biome; @Mixin(Biome.class) public class MixinBiome { - @Inject(method = "getPrecipitation", at = @At("HEAD"), cancellable = true) + @Inject(method = "getPrecipitationAt", at = @At("HEAD"), cancellable = true) public void getPrecipitation(BlockPos pos, int seaLevel, CallbackInfoReturnable cir) { if(WeatherChangerMod.getInstance().isEnabled() && WeatherChangerMod.getInstance().isSnowing()) { diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinClientWorldProperties.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinClientWorldProperties.java index a475077..bafaae8 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinClientWorldProperties.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinClientWorldProperties.java @@ -6,13 +6,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import cn.pupperclient.management.mod.impl.misc.TimeChangerMod; +import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.world.ClientWorld; - -@Mixin(ClientWorld.Properties.class) +@Mixin(ClientLevel.ClientLevelData.class) public class MixinClientWorldProperties { - @Inject(method = "getTimeOfDay", at = @At("HEAD"), cancellable = true) + @Inject(method = "getGameTime", at = @At("HEAD"), cancellable = true) public void getTimeOfDay(CallbackInfoReturnable cir) { if (TimeChangerMod.getInstance().isEnabled()) { cir.setReturnValue(TimeChangerMod.getInstance().getTime()); diff --git a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinWorld.java b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinWorld.java index 9d68272..f3a6329 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinWorld.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/minecraft/world/MixinWorld.java @@ -6,13 +6,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import cn.pupperclient.management.mod.impl.misc.WeatherChangerMod; +import net.minecraft.world.level.Level; -import net.minecraft.world.World; - -@Mixin(World.class) +@Mixin(Level.class) public class MixinWorld { - @Inject(method = "getRainGradient", at = @At("HEAD"), cancellable = true) + @Inject(method = "getRainLevel", at = @At("HEAD"), cancellable = true) public void getRainGradient(float delta, CallbackInfoReturnable cir) { WeatherChangerMod mod = WeatherChangerMod.getInstance(); @@ -33,7 +32,7 @@ public void isRaining(CallbackInfoReturnable cir) { } } - @Inject(method = "getThunderGradient", at = @At("HEAD"), cancellable = true) + @Inject(method = "getThunderLevel", at = @At("HEAD"), cancellable = true) public void getThunderGradient(float delta, CallbackInfoReturnable cir) { WeatherChangerMod mod = WeatherChangerMod.getInstance(); diff --git a/src/main/java/cn/pupperclient/mixin/mixins/viafabricplus/MixinMinecraftClient.java b/src/main/java/cn/pupperclient/mixin/mixins/viafabricplus/MixinMinecraftClient.java index d8e486c..1ef0daa 100644 --- a/src/main/java/cn/pupperclient/mixin/mixins/viafabricplus/MixinMinecraftClient.java +++ b/src/main/java/cn/pupperclient/mixin/mixins/viafabricplus/MixinMinecraftClient.java @@ -5,22 +5,21 @@ import org.spongepowered.asm.mixin.injection.At; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.MultiPlayerGameMode; +import net.minecraft.client.player.LocalPlayer; import cn.pupperclient.management.mod.impl.player.OldAnimationsMod; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.network.ClientPlayerInteractionManager; - -@Mixin(value = MinecraftClient.class, priority = 2000) +@Mixin(value = Minecraft.class, priority = 2000) public class MixinMinecraftClient { @Shadow - public ClientPlayerEntity player; + public LocalPlayer player; @Shadow - public ClientPlayerInteractionManager interactionManager; + public MultiPlayerGameMode gameMode; - @ModifyExpressionValue(method = "doItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;isBreakingBlock()Z")) + @ModifyExpressionValue(method = "startUseItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/MultiPlayerGameMode;isDestroying()Z")) private boolean injectOldAnimation(boolean original) { if(OldAnimationsMod.getInstance().isEnabled()) { diff --git a/src/main/java/cn/pupperclient/shader/ExtendedRenderPipelineBuilder.java b/src/main/java/cn/pupperclient/shader/ExtendedRenderPipelineBuilder.java new file mode 100644 index 0000000..7c95c30 --- /dev/null +++ b/src/main/java/cn/pupperclient/shader/ExtendedRenderPipelineBuilder.java @@ -0,0 +1,28 @@ +package cn.pupperclient.shader; + +import cn.pupperclient.mixin.interfaces.IRenderPipeline; +import com.mojang.blaze3d.pipeline.RenderPipeline; + +public class ExtendedRenderPipelineBuilder extends RenderPipeline.Builder { + private boolean lineSmooth; + + public ExtendedRenderPipelineBuilder(RenderPipeline.Snippet... snippets) { + for (RenderPipeline.Snippet snippet : snippets) { + withSnippet(snippet); + } + } + + public ExtendedRenderPipelineBuilder withLineSmooth() { + lineSmooth = true; + return this; + } + + @Override + public RenderPipeline build() { + RenderPipeline pipeline = super.build(); + ((IRenderPipeline) pipeline).pupper$setLineSmooth(lineSmooth); + + return pipeline; + } +} +// based on meteor diff --git a/src/main/java/cn/pupperclient/shader/Framebuffer.java b/src/main/java/cn/pupperclient/shader/Framebuffer.java deleted file mode 100644 index 9a32327..0000000 --- a/src/main/java/cn/pupperclient/shader/Framebuffer.java +++ /dev/null @@ -1,116 +0,0 @@ -package cn.pupperclient.shader; - -import static org.lwjgl.opengl.GL11C.*; -import static org.lwjgl.opengl.GL12C.GL_CLAMP_TO_EDGE; -import static org.lwjgl.opengl.GL30C.GL_COLOR_ATTACHMENT0; -import static org.lwjgl.opengl.GL30C.GL_FRAMEBUFFER; -import static org.lwjgl.opengl.GL30C.glGenerateMipmap; - -import java.nio.ByteBuffer; - -import org.lwjgl.opengl.GL30C; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.util.Window; - -public class Framebuffer { - - private int id; - public int texture; - public double sizeMulti = 1; - public int width, height; - private boolean mipmapEnabled = false; - - public Framebuffer(double sizeMulti) { - this.sizeMulti = sizeMulti; - init(); - } - - public Framebuffer() { - init(); - } - - private void init() { - Window window = MinecraftClient.getInstance().getWindow(); - - id = GlStateManager.glGenFramebuffers(); - bind(); - - texture = GlStateManager._genTexture(); - ShaderHelper.bindTexture(texture); - ShaderHelper.defaultPixelStore(); - - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - width = Math.max(1, (int) (window.getFramebufferWidth() * sizeMulti)); - height = Math.max(1, (int) (window.getFramebufferHeight() * sizeMulti)); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer) null); - GlStateManager._glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - - unbind(); - } - - public void enableMipmap() { - if (sizeMulti < 1.0) { - mipmapEnabled = true; - bind(); - ShaderHelper.bindTexture(texture); - - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - unbind(); - } - } - - public void generateMipmap() { - if (mipmapEnabled && sizeMulti < 1.0) { - bind(); - ShaderHelper.bindTexture(texture); - ShaderHelper.generateMipmap(GL_TEXTURE_2D); - unbind(); - } - } - - public void bind() { - GlStateManager._glBindFramebuffer(GL_FRAMEBUFFER, id); - } - - public void setViewport() { - RenderSystem.viewport(0, 0, width, height); - } - - public void unbind() { - MinecraftClient.getInstance().getFramebuffer().beginWrite(false); - } - - public void delete() { - if (id != 0) { - GlStateManager._glDeleteFramebuffers(id); - id = 0; - } - if (texture != 0) { - GlStateManager._deleteTexture(texture); - texture = 0; - } - } - - public void resize() { - delete(); - init(); - if (mipmapEnabled) { - enableMipmap(); - } - } -} diff --git a/src/main/java/cn/pupperclient/shader/MeshUniforms.java b/src/main/java/cn/pupperclient/shader/MeshUniforms.java new file mode 100644 index 0000000..e161331 --- /dev/null +++ b/src/main/java/cn/pupperclient/shader/MeshUniforms.java @@ -0,0 +1,48 @@ +package cn.pupperclient.shader; + +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.buffers.Std140Builder; +import com.mojang.blaze3d.buffers.Std140SizeCalculator; +import net.minecraft.client.renderer.DynamicUniformStorage; +import org.joml.Matrix4f; + +import java.nio.ByteBuffer; + +public class MeshUniforms { + public static final int SIZE = new Std140SizeCalculator() + .putMat4f() + .putMat4f() + .get(); + + private static final Data DATA = new Data(); + + private static final DynamicUniformStorage STORAGE = new DynamicUniformStorage<>("Meteor - Mesh UBO", SIZE, 16); + + public static void flipFrame() { + STORAGE.endFrame(); + } + + public static GpuBufferSlice write(Matrix4f proj, Matrix4f modelView) { + DATA.proj = proj; + DATA.modelView = modelView; + + return STORAGE.writeUniform(DATA); + } + + private static final class Data implements DynamicUniformStorage.DynamicUniform { + private Matrix4f proj; + private Matrix4f modelView; + + @Override + public void write(ByteBuffer buffer) { + Std140Builder.intoBuffer(buffer) + .putMat4f(proj) + .putMat4f(modelView); + } + + @Override + public boolean equals(Object o) { + return false; + } + } +} diff --git a/src/main/java/cn/pupperclient/shader/PostProcessRenderer.java b/src/main/java/cn/pupperclient/shader/PostProcessRenderer.java deleted file mode 100644 index e40bbc5..0000000 --- a/src/main/java/cn/pupperclient/shader/PostProcessRenderer.java +++ /dev/null @@ -1,185 +0,0 @@ -package cn.pupperclient.shader; - -import static org.lwjgl.opengl.GL11C.GL_FLOAT; -import static org.lwjgl.opengl.GL11C.GL_UNSIGNED_INT; -import static org.lwjgl.opengl.GL15C.GL_ARRAY_BUFFER; -import static org.lwjgl.opengl.GL15C.GL_DYNAMIC_DRAW; -import static org.lwjgl.opengl.GL15C.GL_ELEMENT_ARRAY_BUFFER; -import static org.lwjgl.system.MemoryUtil.memAddress0; -import static org.lwjgl.system.MemoryUtil.memPutFloat; -import static org.lwjgl.system.MemoryUtil.memPutInt; - -import java.nio.ByteBuffer; - -import org.lwjgl.BufferUtils; -import org.lwjgl.opengl.GL15C; -import org.lwjgl.opengl.GL32C; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; - -import net.minecraft.client.util.math.MatrixStack; - -public class PostProcessRenderer { - - private static final Mesh mesh = new Mesh(); - private static final MatrixStack matrices = new MatrixStack(); - - static { - mesh.begin(); - mesh.quad(mesh.vec2(-1, -1).next(), mesh.vec2(-1, 1).next(), mesh.vec2(1, 1).next(), mesh.vec2(1, -1).next()); - mesh.end(); - } - - public static void beginRender() { - mesh.beginRender(matrices); - } - - public static void render() { - mesh.render(matrices); - } - - public static void endRender() { - mesh.endRender(); - } - - private static class Mesh { - - private final int vao, vbo, ibo; - - private final ByteBuffer vertices; - private final long verticesPointerStart; - private long verticesPointer; - - private final ByteBuffer indices; - private final long indicesPointer; - - private int vertexI, indicesCount; - - private boolean building; - private boolean beganRendering; - - public Mesh() { - int drawMode = 3; - int stride = 8; - - int primitiveVerticesSize = stride * drawMode; - - vertices = BufferUtils.createByteBuffer(primitiveVerticesSize * 256 * 4); - verticesPointerStart = memAddress0(vertices); - - indices = BufferUtils.createByteBuffer(drawMode * 512 * 4); - indicesPointer = memAddress0(indices); - - vao = GlStateManager._glGenVertexArrays(); - GlStateManager._glBindVertexArray(vao); - - vbo = GlStateManager._glGenBuffers(); - GlStateManager._glBindBuffer(GL_ARRAY_BUFFER, vbo); - - ibo = GlStateManager._glGenBuffers(); - GlStateManager._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); - - GlStateManager._enableVertexAttribArray(0); - GlStateManager._vertexAttribPointer(0, 2, GL_FLOAT, false, stride, 0); - - GlStateManager._glBindVertexArray(0); - GlStateManager._glBindBuffer(GL_ARRAY_BUFFER, 0); - GlStateManager._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - - public void begin() { - - if (building) { - return; - } - - verticesPointer = verticesPointerStart; - vertexI = 0; - indicesCount = 0; - - building = true; - } - - public Mesh vec2(double x, double y) { - long p = verticesPointer; - - memPutFloat(p, (float) x); - memPutFloat(p + 4, (float) y); - - verticesPointer += 8; - return this; - } - - public int next() { - return vertexI++; - } - - public void quad(int i1, int i2, int i3, int i4) { - long p = indicesPointer + indicesCount * 4L; - - memPutInt(p, i1); - memPutInt(p + 4, i2); - memPutInt(p + 8, i3); - - memPutInt(p + 12, i3); - memPutInt(p + 16, i4); - memPutInt(p + 20, i1); - - indicesCount += 6; - } - - public void end() { - - if (!building) { - return; - } - - if (indicesCount > 0) { - GlStateManager._glBindBuffer(GL_ARRAY_BUFFER, vbo); - GlStateManager._glBufferData(GL_ARRAY_BUFFER, vertices.limit(getVerticesOffset()), GL_DYNAMIC_DRAW); - GlStateManager._glBindBuffer(GL_ARRAY_BUFFER, 0); - - GlStateManager._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); - GlStateManager._glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.limit(indicesCount * 4), GL_DYNAMIC_DRAW); - GlStateManager._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - - building = false; - } - - public void beginRender(MatrixStack matrices) { - RenderSystem.disableCull(); - beganRendering = true; - } - - public void render(MatrixStack matrices) { - if (building) - end(); - - if (indicesCount > 0) { - boolean wasBeganRendering = beganRendering; - if (!wasBeganRendering) - beginRender(matrices); - - Shader.BOUND.setDefaults(); - - GlStateManager._glBindVertexArray(vao); - RenderSystem.drawElements(GL32C.GL_TRIANGLES, indicesCount, GL_UNSIGNED_INT); - - GlStateManager._glBindVertexArray(0); - - if (!wasBeganRendering) - endRender(); - } - } - - public void endRender() { - beganRendering = false; - } - - private int getVerticesOffset() { - return (int) (verticesPointer - verticesPointerStart); - } - } -} diff --git a/src/main/java/cn/pupperclient/shader/PupperFullScreenRenderer.java b/src/main/java/cn/pupperclient/shader/PupperFullScreenRenderer.java new file mode 100644 index 0000000..b3a59a7 --- /dev/null +++ b/src/main/java/cn/pupperclient/shader/PupperFullScreenRenderer.java @@ -0,0 +1,37 @@ +package cn.pupperclient.shader; + +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.vertex.VertexFormat; + +public class PupperFullScreenRenderer { + public static GpuBuffer vbo; + public static GpuBuffer ibo; + + /** + * Deprecated for performance reasons, use {@link PupperMeshRenderer#fullscreen()} or the {@link PupperFullScreenRenderer#vbo} + * and {@link PupperFullScreenRenderer#ibo} buffer objects instead. + */ + @Deprecated(forRemoval = true) + public static PupperMeshBuilder mesh; + + private PupperFullScreenRenderer() {} + + static { + mesh = new PupperMeshBuilder(PupperVertexFormats.POS2, VertexFormat.Mode.TRIANGLES); + + mesh.begin(); + + mesh.quad( + mesh.vec2(-1, -1).next(), + mesh.vec2(-1, 1).next(), + mesh.vec2(1, 1).next(), + mesh.vec2(1, -1).next() + ); + + mesh.end(); + + vbo = mesh.getVertexBuffer(); + ibo = mesh.getIndexBuffer(); + } +} +// based on meteor diff --git a/src/main/java/cn/pupperclient/shader/PupperMeshBuilder.java b/src/main/java/cn/pupperclient/shader/PupperMeshBuilder.java new file mode 100644 index 0000000..fa099e9 --- /dev/null +++ b/src/main/java/cn/pupperclient/shader/PupperMeshBuilder.java @@ -0,0 +1,201 @@ +package cn.pupperclient.shader; + +import cn.pupperclient.utils.color.Color; +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.fabricmc.loader.api.FabricLoader; +import org.lwjgl.BufferUtils; + +import java.nio.ByteBuffer; + +import static org.lwjgl.system.MemoryUtil.*; + +public class PupperMeshBuilder { + private static final boolean DEBUG = FabricLoader.getInstance().isDevelopmentEnvironment(); + + public double alpha = 1; + + private final VertexFormat format; + private final int primitiveVerticesSize; + private final int primitiveIndicesCount; + + private ByteBuffer vertices = null; + private long verticesPointerStart, verticesPointer; + + private ByteBuffer indices = null; + private long indicesPointer; + + private int vertexI, indicesCount; + + private boolean building; + + public PupperMeshBuilder(RenderPipeline pipeline) { + this(pipeline.getVertexFormat(), pipeline.getVertexFormatMode()); + } + + public PupperMeshBuilder(VertexFormat format, VertexFormat.Mode mode) { + this.format = format; + primitiveVerticesSize = format.getVertexSize(); + primitiveIndicesCount = mode.connectedPrimitives ? mode.primitiveStride : mode.primitiveLength; + } + + public PupperMeshBuilder(VertexFormat format, VertexFormat.Mode drawMode, int vertexCount, int indexCount) { + this(format, drawMode); + allocateBuffers(vertexCount, indexCount); + } + + public void begin() { + if (building) throw new IllegalStateException("Mesh.begin() called while already building."); + + verticesPointer = verticesPointerStart; + vertexI = 0; + indicesCount = 0; + + building = true; + } + + public PupperMeshBuilder vec2(double x, double y) { + debugVertexBufferCapacity(); + + long p = verticesPointer; + + memPutFloat(p, (float) x); + memPutFloat(p + 4, (float) y); + + verticesPointer += 8; + return this; + } + + public PupperMeshBuilder color(Color c) { + debugVertexBufferCapacity(); + + long p = verticesPointer; + + memPutByte(p, (byte) c.r); + memPutByte(p + 1, (byte) c.g); + memPutByte(p + 2, (byte) c.b); + memPutByte(p + 3, (byte) (c.a * (float) alpha)); + + verticesPointer += 4; + return this; + } + + public int next() { + return vertexI++; + } + + public void line(int i1, int i2) { + debugIndexBufferCapacity(); + memPutInt(indicesPointer, i1); + memPutInt(indicesPointer + 4, i2); + indicesPointer += 8; + indicesCount += 2; + } + + public void quad(int i1, int i2, int i3, int i4) { + debugIndexBufferCapacity(); + memPutInt(indicesPointer, i1); + memPutInt(indicesPointer + 4, i2); + memPutInt(indicesPointer + 8, i3); + memPutInt(indicesPointer + 12, i1); + memPutInt(indicesPointer + 16, i3); + memPutInt(indicesPointer + 20, i4); + indicesPointer += 24; + indicesCount += 6; + } + + public void ensureQuadCapacity() { + ensureCapacity(4, 6); + } + + public void ensureTriCapacity() { + ensureCapacity(3, 3); + } + + public void ensureLineCapacity() { + ensureCapacity(2, 2); + } + + public void ensureCapacity(int vertexCount, int indexCount) { + if (DEBUG && (indexCount % primitiveIndicesCount != 0)) { + throw new IllegalArgumentException("Unexpected amount of indices written to MeshBuilder."); + } + + if (vertices == null || indices == null) { + allocateBuffers(256 * 4, 512 * 4); + return; + } + + if ((vertexI + vertexCount) * primitiveVerticesSize >= vertices.capacity()) { + int offset = getVerticesOffset(); + int newSize = Math.max(vertices.capacity() * 2, vertices.capacity() + vertexCount * primitiveVerticesSize); + ByteBuffer newVertices = BufferUtils.createByteBuffer(newSize); + memCopy(memAddress0(vertices), memAddress0(newVertices), offset); + + vertices = newVertices; + verticesPointerStart = memAddress0(vertices); + verticesPointer = verticesPointerStart + offset; + } + + if ((indicesCount + indexCount) * Integer.BYTES >= indices.capacity()) { + int newSize = Math.max(indices.capacity() * 2, indices.capacity() + indexCount * Integer.BYTES); + + ByteBuffer newIndices = BufferUtils.createByteBuffer(newSize); + memCopy(memAddress0(indices), memAddress0(newIndices), indicesCount * 4L); + + indices = newIndices; + indicesPointer = memAddress0(indices); + } + } + + public void end() { + if (!building) throw new IllegalStateException("Mesh.end() called while not building."); + + building = false; + } + + public GpuBuffer getVertexBuffer() { + vertices.limit(getVerticesOffset()); + return format.uploadImmediateVertexBuffer(vertices); + } + + public GpuBuffer getIndexBuffer() { + indices.limit(indicesCount * 4); + return format.uploadImmediateIndexBuffer(indices); + } + + public PupperMeshBuilder tex2(float u, float v) { + memPutFloat(verticesPointer, u); + memPutFloat(verticesPointer + 4, v); + verticesPointer += 8; + return this; + } + + public int getIndicesCount() { return indicesCount; } + private int getVerticesOffset() { return (int) (verticesPointer - verticesPointerStart); } + + private void allocateBuffers(int vertexCount, int indexCount) { + vertices = BufferUtils.createByteBuffer(primitiveVerticesSize * vertexCount); + verticesPointer = verticesPointerStart = memAddress0(vertices); + + indices = BufferUtils.createByteBuffer(indexCount * Integer.BYTES); + indicesPointer = memAddress0(indices); + } + + private void debugVertexBufferCapacity() { + if (DEBUG && (vertices == null || vertexI * primitiveVerticesSize >= vertices.capacity())) { + throw new IndexOutOfBoundsException("Vertices written to MeshBuilder without calling 'ensureCapacity()' first!"); + } + } + + private void debugIndexBufferCapacity() { + if (DEBUG && (indices == null || indicesCount * Integer.BYTES >= indices.capacity())) { + throw new IndexOutOfBoundsException("Indices written to MeshBuilder without calling 'ensureCapacity()' first!"); + } + } + + public boolean isBuilding() { + return building; + } +} diff --git a/src/main/java/cn/pupperclient/shader/PupperMeshRenderer.java b/src/main/java/cn/pupperclient/shader/PupperMeshRenderer.java new file mode 100644 index 0000000..2977b28 --- /dev/null +++ b/src/main/java/cn/pupperclient/shader/PupperMeshRenderer.java @@ -0,0 +1,162 @@ +package cn.pupperclient.shader; + +import cn.pupperclient.utils.color.Color; +import cn.pupperclient.utils.render.RenderUtils; +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.systems.RenderPass; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.GpuSampler; +import com.mojang.blaze3d.textures.GpuTextureView; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.util.ARGB; +import net.minecraft.util.Tuple; +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; + +import java.util.HashMap; +import java.util.OptionalDouble; +import java.util.OptionalInt; + +public class PupperMeshRenderer { + private static final PupperMeshRenderer INSTANCE = new PupperMeshRenderer(); + + private static boolean taken; + + private GpuTextureView colorAttachment; + private GpuTextureView depthAttachment; + private Color clearColor; + private RenderPipeline pipeline; + private @Nullable PupperMeshBuilder mesh; + private @Nullable GpuBuffer vertexBuffer; + private @Nullable GpuBuffer indexBuffer; + private Matrix4f matrix; + private final HashMap uniforms = new HashMap<>(); + private final HashMap> samplers = new HashMap<>(); + + PupperMeshRenderer() {} + + public static PupperMeshRenderer begin() { + if (taken) throw new IllegalStateException("MeshRenderer already taken."); + taken = true; + + return INSTANCE; + } + + public PupperMeshRenderer attachments(RenderTarget framebuffer) { + colorAttachment = framebuffer.getColorTextureView(); + depthAttachment = framebuffer.getDepthTextureView(); + return this; + } + + public PupperMeshRenderer attachments(GpuTextureView color, GpuTextureView depth) { + colorAttachment = color; + depthAttachment = depth; + return this; + } + + public PupperMeshRenderer pipeline(RenderPipeline pipeline) { + this.pipeline = pipeline; + return this; + } + + public PupperMeshRenderer mesh(PupperMeshBuilder mesh) { + this.mesh = mesh; + return this; + } + + public PupperMeshRenderer mesh(PupperMeshBuilder mesh, Matrix4f matrix) { + this.mesh = mesh; + return this.transform(matrix); + } + + public PupperMeshRenderer mesh(PupperMeshBuilder mesh, PoseStack matrices) { + this.mesh = mesh; + return this.transform(matrices); + } + + public PupperMeshRenderer mesh(GpuBuffer vertices, GpuBuffer indices) { + this.vertexBuffer = vertices; + this.indexBuffer = indices; + return this; + } + + public PupperMeshRenderer transform(Matrix4f matrix) { + this.matrix = matrix; + return this; + } + + public PupperMeshRenderer transform(PoseStack matrices) { + this.matrix = matrices.last().pose(); + return this; + } + + public PupperMeshRenderer fullscreen() { + return this.mesh(PupperFullScreenRenderer.vbo, PupperFullScreenRenderer.ibo); + } + + public PupperMeshRenderer uniform(String name, GpuBufferSlice slice) { + uniforms.put(name, slice); + return this; + } + + public PupperMeshRenderer sampler(String name, GpuTextureView view, GpuSampler sampler) { + if (name != null && view != null && sampler != null) { + samplers.put(name, new Tuple<>(view, sampler)); + } + + return this; + } + + public void end() { + int indexCount = mesh != null ? mesh.getIndicesCount() + : (int) (indexBuffer != null ? indexBuffer.size() / Integer.BYTES : -1); + + if (pipeline != null && mesh != null && indexCount > 0) { + GpuBuffer vertexBuffer = mesh.getVertexBuffer(); + GpuBuffer indexBuffer = mesh != null ? mesh.getIndexBuffer() : this.indexBuffer; + + if (vertexBuffer != null && indexBuffer != null) { + GpuBufferSlice meshData = MeshUniforms.write(RenderUtils.projection, RenderSystem.getModelViewStack()); + + OptionalInt clearColor = this.clearColor != null ? + OptionalInt.of(ARGB.color(this.clearColor.a, this.clearColor.r, this.clearColor.g, this.clearColor.b)) : + OptionalInt.empty(); + + RenderPass pass = (depthAttachment != null && pipeline.wantsDepthTexture()) ? + RenderSystem.getDevice().createCommandEncoder().createRenderPass(() -> "Pupper MeshRenderer", colorAttachment, clearColor, depthAttachment, OptionalDouble.empty()) : + RenderSystem.getDevice().createCommandEncoder().createRenderPass(() -> "Pupper MeshRenderer", colorAttachment, clearColor); + + pass.setPipeline(pipeline); + pass.setUniform("MeshData", meshData); + + for (var entry : uniforms.entrySet()) { + pass.setUniform(entry.getKey(), entry.getValue()); + } + + for (var entry : samplers.entrySet()) { + pass.bindTexture(entry.getKey(), entry.getValue().getA(), entry.getValue().getB()); + } + + pass.setVertexBuffer(0, vertexBuffer); + pass.setIndexBuffer(indexBuffer, VertexFormat.IndexType.INT); + pass.drawIndexed(0, 0, indexCount, 1); + + pass.close(); + } + } + + colorAttachment = null; + depthAttachment = null; + clearColor = null; + pipeline = null; + mesh = null; + matrix = null; + + taken = false; + } +} +// based on meteor diff --git a/src/main/java/cn/pupperclient/shader/PupperRenderPipelines.java b/src/main/java/cn/pupperclient/shader/PupperRenderPipelines.java new file mode 100644 index 0000000..0e8b52e --- /dev/null +++ b/src/main/java/cn/pupperclient/shader/PupperRenderPipelines.java @@ -0,0 +1,144 @@ +package cn.pupperclient.shader; + +import com.mojang.blaze3d.pipeline.BlendFunction; +import com.mojang.blaze3d.pipeline.ColorTargetState; +import com.mojang.blaze3d.pipeline.DepthStencilState; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.platform.CompareOp; +import com.mojang.blaze3d.shaders.UniformType; +import com.mojang.blaze3d.systems.GpuDevice; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.Minecraft; +import net.minecraft.resources.Identifier; +import net.minecraft.server.packs.resources.ResourceManager; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +public abstract class PupperRenderPipelines { + private static final List PIPELINES = new ArrayList<>(); + + private static final RenderPipeline.Snippet MESH_UNIFORMS = RenderPipeline.builder() + .withUniform("MeshData", UniformType.UNIFORM_BUFFER) + .buildSnippet(); + + + // Blur + public static final RenderPipeline BLUR_DOWN = add(new ExtendedRenderPipelineBuilder(MESH_UNIFORMS) + .withLocation(getLocation("pipeline/blur_down")) + .withVertexFormat(PupperVertexFormats.POS2, VertexFormat.Mode.TRIANGLES) + .withVertexShader(getLocation("blur")) + .withFragmentShader(getLocation("blur_down")) + .withSampler("u_Texture") + .withUniform("BlurData", UniformType.UNIFORM_BUFFER) + .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) + .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) + .withCull(false) + .build() + ); + + public static final RenderPipeline BLUR_UP = add(new ExtendedRenderPipelineBuilder(MESH_UNIFORMS) + .withLocation(getLocation("pipeline/blur_up")) + .withVertexFormat(PupperVertexFormats.POS2, VertexFormat.Mode.TRIANGLES) + .withVertexShader(getLocation("blur")) + .withFragmentShader(getLocation("blur_up")) + .withSampler("u_Texture") + .withUniform("BlurData", UniformType.UNIFORM_BUFFER) + .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) + .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) + .withCull(false) + .build() + ); + + public static final RenderPipeline BLUR_PASSTHROUGH = add(new ExtendedRenderPipelineBuilder(MESH_UNIFORMS) + .withLocation(getLocation("pipeline/passthrough")) + .withVertexFormat(PupperVertexFormats.POS2, VertexFormat.Mode.TRIANGLES) + .withVertexShader(getLocation("passthrough")) + .withFragmentShader(getLocation("passthrough")) + .withSampler("Sampler0") + .withSampler("u_Texture") + .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) + .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) + .withCull(false) + .build() + ); + +// +// // UI +// public static final RenderPipeline UI_COLORED = add(new ExtendedRenderPipelineBuilder(MESH_UNIFORMS) +// .withLocation(getLocation("pipeline/ui_colored")) +// .withVertexFormat(PupperVertexFormats.POS2_COLOR, VertexFormat.Mode.TRIANGLES) +// .withVertexShader(getLocation("ui_colored")) +// .withFragmentShader(getLocation("ui_colored")) +// .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) +// .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) +// .withCull(true) +// .build() +// ); +// +// public static final RenderPipeline UI_COLORED_LINES = add(new ExtendedRenderPipelineBuilder(MESH_UNIFORMS) +// .withLineSmooth() +// .withLocation(getLocation("pipeline/ui_colored_lines")) +// .withVertexFormat(PupperVertexFormats.POS2_COLOR, VertexFormat.Mode.LINES) +// .withVertexShader(getLocation("ui_colored")) +// .withFragmentShader(getLocation("ui_colored")) +// .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) +// .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) +// .withCull(true) +// .build() +// ); +// +// public static final RenderPipeline UI_TEXTURED = add(new ExtendedRenderPipelineBuilder(MESH_UNIFORMS) +// .withLocation(getLocation("pipeline/ui_textured")) +// .withVertexFormat(PupperVertexFormats.POS2_COLOR_TEX, VertexFormat.Mode.TRIANGLES) +// .withVertexShader(getLocation("ui_textured")) +// .withFragmentShader(getLocation("ui_textured")) +// .withSampler("u_Texture") +// .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) +// .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) +// .withCull(true) +// .build() +// ); +// +// public static final RenderPipeline UI_ROUNDED_TEXTURED = add(new ExtendedRenderPipelineBuilder(MESH_UNIFORMS) +// .withLocation(getLocation("pipeline/ui_rounded_textured")) +// .withVertexFormat(PupperVertexFormats.POS2_COLOR_TEX, VertexFormat.Mode.TRIANGLES) +// .withVertexShader(getLocation("ui_textured")) +// .withFragmentShader(getLocation("ui_rounded_textured")) +// .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) +// .build() +// ); + + private static RenderPipeline add(RenderPipeline pipeline) { + PIPELINES.add(pipeline); + return pipeline; + } + + private PupperRenderPipelines() {} + + public static void precompile() { + GpuDevice device = RenderSystem.getDevice(); + ResourceManager resources = Minecraft.getInstance().getResourceManager(); + + for (RenderPipeline pipeline : PIPELINES) { + device.precompilePipeline(pipeline, (identifier, shaderType) -> { + var resource = resources.getResource(identifier).get(); + + try (var in = resource.open()) { + return IOUtils.toString(in, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } + } + + private static Identifier getLocation(String path) { + return Identifier.fromNamespaceAndPath("pupper", path); + } +} +// based on meteor diff --git a/src/main/java/cn/pupperclient/shader/PupperVertexFormatElements.java b/src/main/java/cn/pupperclient/shader/PupperVertexFormatElements.java new file mode 100644 index 0000000..223d77a --- /dev/null +++ b/src/main/java/cn/pupperclient/shader/PupperVertexFormatElements.java @@ -0,0 +1,24 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package cn.pupperclient.shader; + +import com.mojang.blaze3d.vertex.VertexFormatElement; + +public abstract class PupperVertexFormatElements { + public static final VertexFormatElement POS2 = VertexFormatElement.register(getNextVertexFormatElementId(), 0, VertexFormatElement.Type.FLOAT, false, 2); + + private PupperVertexFormatElements() {} + + private static int getNextVertexFormatElementId() { + int id = 0; + while (VertexFormatElement.byId(id) != null) { + id++; + if (id >= 32) throw new RuntimeException("Too many mods registering VertexFormatElements"); + } + return id; + } +} +// based on meteor diff --git a/src/main/java/cn/pupperclient/shader/PupperVertexFormats.java b/src/main/java/cn/pupperclient/shader/PupperVertexFormats.java new file mode 100644 index 0000000..fd481e9 --- /dev/null +++ b/src/main/java/cn/pupperclient/shader/PupperVertexFormats.java @@ -0,0 +1,24 @@ +package cn.pupperclient.shader; + +import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.blaze3d.vertex.VertexFormatElement; + +public abstract class PupperVertexFormats { + public static final VertexFormat POS2 = VertexFormat.builder() + .add("Position", PupperVertexFormatElements.POS2) + .build(); + + public static final VertexFormat POS2_COLOR = VertexFormat.builder() + .add("Position", PupperVertexFormatElements.POS2) + .add("Color", VertexFormatElement.COLOR) + .build(); + + public static final VertexFormat POS2_COLOR_TEX = VertexFormat.builder() + .add("Position", VertexFormatElement.POSITION) + .add("Color", VertexFormatElement.COLOR) + .add("UV0", VertexFormatElement.UV0) + .build(); + + private PupperVertexFormats() {} +} +// based on meteor diff --git a/src/main/java/cn/pupperclient/shader/Shader.java b/src/main/java/cn/pupperclient/shader/Shader.java deleted file mode 100644 index a2fc2e9..0000000 --- a/src/main/java/cn/pupperclient/shader/Shader.java +++ /dev/null @@ -1,138 +0,0 @@ -package cn.pupperclient.shader; - -import static org.lwjgl.opengl.GL11C.GL_FALSE; -import static org.lwjgl.opengl.GL11C.GL_TRUE; -import static org.lwjgl.opengl.GL20C.GL_FRAGMENT_SHADER; -import static org.lwjgl.opengl.GL20C.GL_VERTEX_SHADER; -import static org.lwjgl.opengl.GL20C.glDeleteProgram; - -import java.io.IOException; -import java.nio.FloatBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.io.IOUtils; -import org.joml.Matrix4f; -import org.lwjgl.BufferUtils; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.Identifier; - -public class Shader { - - public static Shader BOUND; - private final int id; - private final Map locations = new HashMap<>(); - - private static final FloatBuffer MAT = BufferUtils.createFloatBuffer(16); - - public Shader(String vertPath, String fragPath) { - int vertex = GlStateManager.glCreateShader(GL_VERTEX_SHADER); - int fragment = GlStateManager.glCreateShader(GL_FRAGMENT_SHADER); - - GlStateManager.glShaderSource(vertex, read(vertPath)); - GlStateManager.glShaderSource(fragment, read(fragPath)); - - String vertexLog = ShaderHelper.compileShader(vertex); - String fragmentLog = ShaderHelper.compileShader(fragment); - - if (vertexLog != null || fragmentLog != null) { - System.err.println("Vertex Log (" + vertPath + "): " + vertexLog); - System.err.println("Fragment Log (" + fragPath + "): " + fragmentLog); - } - - this.id = GlStateManager.glCreateProgram(); - String programLog = ShaderHelper.linkProgram(id, vertex, fragment); - - if (programLog != null) { - System.err.println("Program Log (" + vertPath + ", " + fragPath + "): " + programLog); - } - - GlStateManager.glDeleteShader(vertex); - GlStateManager.glDeleteShader(fragment); - } - - public void set(String name, double v) { - set(name, (float) v); - } - - public void set(String name, double v1, double v2) { - set(name, (float) v1, (float) v2); - } - - private String read(String path) { - try { - return IOUtils.toString( - MinecraftClient.getInstance().getResourceManager() - .getResource(Identifier.of("pupper", "shaders/" + path)).get().getInputStream(), - StandardCharsets.UTF_8); - } catch (IOException e) { - throw new IllegalStateException("Could not read shader '" + path + "'", e); - } - } - - public void bind() { - ShaderHelper.useProgram(id); - BOUND = this; - } - - public int getLocation(String name) { - if (locations.containsKey(name)) { - return locations.get(name); - } - - int location = ShaderHelper.getUniformLocation(id, name); - locations.put(name, location); - - return location; - } - - public void set(String name, int v) { - ShaderHelper.uniformInt(getLocation(name), v); - } - - public void set(String name, float v) { - ShaderHelper.uniformFloat(getLocation(name), v); - } - - public void set(String name, float v1, float v2) { - ShaderHelper.uniformFloat2(getLocation(name), v1, v2); - } - - public void set(String name, float v1, float v2, float v3) { - ShaderHelper.uniformFloat3(getLocation(name), v1, v2, v3); - } - - public void set(String name, float v1, float v2, float v3, float v4) { - ShaderHelper.uniformFloat4(getLocation(name), v1, v2, v3, v4); - } - - public void set(String name, float[] v) { - ShaderHelper.uniformFloat3Array(getLocation(name), v); - } - - public void set(String name, Matrix4f mat) { - mat.get(MAT); - ShaderHelper.uniformMatrix4(getLocation(name), false, MAT); - } - - public void setDefaults() { - set("u_Proj", RenderSystem.getProjectionMatrix()); - // Modern approach: use RenderSystem matrices directly or pass from context - } - - public void unbind() { - ShaderHelper.useProgram(0); - BOUND = null; - } - - public void delete() { - org.lwjgl.opengl.GL20C.glDeleteProgram(id); - } -} diff --git a/src/main/java/cn/pupperclient/shader/ShaderHelper.java b/src/main/java/cn/pupperclient/shader/ShaderHelper.java deleted file mode 100644 index e7504ba..0000000 --- a/src/main/java/cn/pupperclient/shader/ShaderHelper.java +++ /dev/null @@ -1,203 +0,0 @@ -package cn.pupperclient.shader; - -import static org.lwjgl.opengl.GL11C.GL_FALSE; -import static org.lwjgl.opengl.GL11C.GL_LINE_SMOOTH; -import static org.lwjgl.opengl.GL11C.GL_ONE_MINUS_SRC_ALPHA; -import static org.lwjgl.opengl.GL11C.GL_SRC_ALPHA; -import static org.lwjgl.opengl.GL11C.GL_UNPACK_ALIGNMENT; -import static org.lwjgl.opengl.GL11C.GL_UNPACK_LSB_FIRST; -import static org.lwjgl.opengl.GL11C.GL_UNPACK_ROW_LENGTH; -import static org.lwjgl.opengl.GL11C.GL_UNPACK_SKIP_PIXELS; -import static org.lwjgl.opengl.GL11C.GL_UNPACK_SKIP_ROWS; -import static org.lwjgl.opengl.GL11C.GL_UNPACK_SWAP_BYTES; -import static org.lwjgl.opengl.GL11C.glDisable; -import static org.lwjgl.opengl.GL11C.glEnable; -import static org.lwjgl.opengl.GL11C.glLineWidth; -import static org.lwjgl.opengl.GL11C.glTexImage2D; -import static org.lwjgl.opengl.GL12C.GL_UNPACK_IMAGE_HEIGHT; -import static org.lwjgl.opengl.GL12C.GL_UNPACK_SKIP_IMAGES; -import static org.lwjgl.opengl.GL13C.GL_TEXTURE0; -import static org.lwjgl.opengl.GL15C.GL_ELEMENT_ARRAY_BUFFER; -import static org.lwjgl.opengl.GL20C.*; -import static org.lwjgl.opengl.GL30C.*; - -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; - -import com.mojang.blaze3d.platform.GlStateManager; -import cn.pupperclient.mixin.mixins.minecraft.client.render.BufferRendererAccessor; - -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.texture.AbstractTexture; -import net.minecraft.util.Identifier; - -public class ShaderHelper { - public static int CURRENT_IBO; - private static int prevIbo; - - private ShaderHelper() {} - - public static void bindVertexArray(int vao) { - GlStateManager._glBindVertexArray(vao); - BufferRendererAccessor.setCurrentVertexBuffer(null); - } - - public static void bindIndexBuffer(int ibo) { - if (ibo != 0) - prevIbo = CURRENT_IBO; - GlStateManager._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo != 0 ? ibo : prevIbo); - } - - public static String compileShader(int shader) { - GlStateManager.glCompileShader(shader); - - if (GlStateManager.glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE) { - return GlStateManager.glGetShaderInfoLog(shader, 512); - } - - return null; - } - - public static String linkProgram(int program, int vertShader, int fragShader) { - GlStateManager.glAttachShader(program, vertShader); - GlStateManager.glAttachShader(program, fragShader); - GlStateManager.glLinkProgram(program); - - if (GlStateManager.glGetProgrami(program, GL_LINK_STATUS) == GL_FALSE) { - return GlStateManager.glGetProgramInfoLog(program, 512); - } - - return null; - } - - public static void useProgram(int program) { - RenderSystem.setShaderGameTime(System.currentTimeMillis(), 0); - GlStateManager._glUseProgram(program); - } - - public static void viewport(int x, int y, int width, int height) { - RenderSystem.viewport(x, y, width, height); - } - - public static int getUniformLocation(int program, String name) { - return GlStateManager._glGetUniformLocation(program, name); - } - - public static void uniformInt(int location, int v) { - // No direct RenderSystem wrapper for uniform1i by location, use GlStateManager if available or native - // GlStateManager doesn't have uniform1i usually, RenderSystem has it for ShaderInstance but not raw programs - // For raw programs, we might need native or a helper. - // Actually, GlStateManager often has _glUniform1i but let's check. - // If not, we stay with native for uniforms if no wrapper exists. - org.lwjgl.opengl.GL20C.glUniform1i(location, v); - } - - public static void uniformFloat(int location, float v) { - org.lwjgl.opengl.GL20C.glUniform1f(location, v); - } - - public static void uniformFloat2(int location, float v1, float v2) { - org.lwjgl.opengl.GL20C.glUniform2f(location, v1, v2); - } - - public static void uniformFloat3(int location, float v1, float v2, float v3) { - org.lwjgl.opengl.GL20C.glUniform3f(location, v1, v2, v3); - } - - public static void uniformFloat4(int location, float v1, float v2, float v3, float v4) { - org.lwjgl.opengl.GL20C.glUniform4f(location, v1, v2, v3, v4); - } - - public static void uniformFloat3Array(int location, float[] v) { - org.lwjgl.opengl.GL20C.glUniform3fv(location, v); - } - - public static void uniformMatrix4(int location, boolean transpose, FloatBuffer matrices) { - org.lwjgl.opengl.GL20C.glUniformMatrix4fv(location, transpose, matrices); - } - - public static void pixelStore(int name, int param) { - RenderSystem.pixelStore(name, param); - } - - public static void textureParam(int target, int name, int param) { - RenderSystem.texParameter(target, name, param); - } - - public static void textureImage2D(int target, int level, int internalFormat, int width, int height, int border, - int format, int type, ByteBuffer pixels) { - glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels); - } - - public static void defaultPixelStore() { - pixelStore(GL_UNPACK_SWAP_BYTES, GL_FALSE); - pixelStore(GL_UNPACK_LSB_FIRST, GL_FALSE); - pixelStore(GL_UNPACK_ROW_LENGTH, 0); - pixelStore(GL_UNPACK_IMAGE_HEIGHT, 0); - pixelStore(GL_UNPACK_SKIP_ROWS, 0); - pixelStore(GL_UNPACK_SKIP_PIXELS, 0); - pixelStore(GL_UNPACK_SKIP_IMAGES, 0); - pixelStore(GL_UNPACK_ALIGNMENT, 4); - } - - public static void framebufferTexture2D(int target, int attachment, int textureTarget, int texture, int level) { - GlStateManager._glFramebufferTexture2D(target, attachment, textureTarget, texture, level); - } - - public static void enableDepth() { - RenderSystem.enableDepthTest(); - } - - public static void disableDepth() { - RenderSystem.disableDepthTest(); - } - - public static void enableBlend() { - RenderSystem.enableBlend(); - RenderSystem.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - public static void disableBlend() { - RenderSystem.disableBlend(); - } - - public static void enableCull() { - RenderSystem.enableCull(); - } - - public static void disableCull() { - RenderSystem.disableCull(); - } - - public static void enableLineSmooth() { - glEnable(GL_LINE_SMOOTH); - glLineWidth(1); - } - - public static void disableLineSmooth() { - glDisable(GL_LINE_SMOOTH); - } - - public static void bindTexture(Identifier id) { - AbstractTexture texture = MinecraftClient.getInstance().getTextureManager().getTexture(id); - bindTexture(texture.getGlId(), 0); - } - - public static void bindTexture(int i, int slot) { - RenderSystem.activeTexture(GL_TEXTURE0 + slot); - RenderSystem.bindTexture(i); - } - - public static void bindTexture(int i) { - bindTexture(i, 0); - } - - public static void resetTextureSlot() { - RenderSystem.activeTexture(GL_TEXTURE0); - } - - public static void generateMipmap(int target) { - glGenerateMipmap(target); - } -} diff --git a/src/main/java/cn/pupperclient/shader/impl/Kawaseblur.java b/src/main/java/cn/pupperclient/shader/impl/Kawaseblur.java index 13a1bf3..24b6849 100644 --- a/src/main/java/cn/pupperclient/shader/impl/Kawaseblur.java +++ b/src/main/java/cn/pupperclient/shader/impl/Kawaseblur.java @@ -1,104 +1,212 @@ package cn.pupperclient.shader.impl; -import cn.pupperclient.management.mod.impl.settings.SystemSettings; +import cn.pupperclient.event.EventBus; +import cn.pupperclient.event.EventListener; +import cn.pupperclient.event.client.ResolutionChangedEvent; +import cn.pupperclient.gui.modmenu.GuiModMenu; +import cn.pupperclient.management.mod.impl.settings.HUDModSettings; +import cn.pupperclient.management.mod.impl.settings.ModMenuSettings; import cn.pupperclient.shader.*; - -import cn.pupperclient.utils.time.TimerUtils; -import it.unimi.dsi.fastutil.ints.IntDoubleImmutablePair; -import net.minecraft.client.MinecraftClient; +import cn.pupperclient.shader.patch.FixedUniformStorage; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.buffers.Std140Builder; +import com.mojang.blaze3d.buffers.Std140SizeCalculator; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.textures.FilterMode; +import com.mojang.blaze3d.textures.GpuTextureView; +import com.mojang.blaze3d.textures.TextureFormat; +import it.unimi.dsi.fastutil.ints.IntFloatImmutablePair; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.DynamicUniformStorage; +import org.jspecify.annotations.NonNull; + +import java.nio.ByteBuffer; public class Kawaseblur { + public static final Kawaseblur instance = new Kawaseblur(); + private final Minecraft mc = Minecraft.getInstance(); + + private final IntFloatImmutablePair[] strengths = new IntFloatImmutablePair[]{ + IntFloatImmutablePair.of(1, 1.25f), // LVL 1 + IntFloatImmutablePair.of(1, 2.25f), // LVL 2 + IntFloatImmutablePair.of(2, 2.0f), // LVL 3 + IntFloatImmutablePair.of(2, 3.0f), // LVL 4 + IntFloatImmutablePair.of(2, 4.25f), // LVL 5 + IntFloatImmutablePair.of(3, 2.5f), // LVL 6 + IntFloatImmutablePair.of(3, 3.25f), // LVL 7 + IntFloatImmutablePair.of(3, 4.25f), // LVL 8 + IntFloatImmutablePair.of(3, 5.5f), // LVL 9 + IntFloatImmutablePair.of(4, 3.25f), // LVL 10 + IntFloatImmutablePair.of(4, 4.0f), // LVL 11 + IntFloatImmutablePair.of(4, 5.0f), // LVL 12 + IntFloatImmutablePair.of(4, 6.0f), // LVL 13 + IntFloatImmutablePair.of(4, 7.25f), // LVL 14 + IntFloatImmutablePair.of(4, 8.25f), // LVL 15 + IntFloatImmutablePair.of(5, 4.5f), // LVL 16 + IntFloatImmutablePair.of(5, 5.25f), // LVL 17 + IntFloatImmutablePair.of(5, 6.25f), // LVL 18 + IntFloatImmutablePair.of(5, 7.25f), // LVL 19 + IntFloatImmutablePair.of(5, 8.5f) // LVL 20 + }; + + private final GpuTextureView[] fbos = new GpuTextureView[6]; + private GpuBufferSlice[] ubos; + + private boolean enabled; + private long fadeEndAt; + private float previousOffset = -1; + + private Kawaseblur() { + EventBus.getInstance().register(this); - public static final Kawaseblur GUI_BLUR = new Kawaseblur(); - public static final Kawaseblur INGAME_BLUR = new Kawaseblur(); - - private static final IntDoubleImmutablePair[] STRENGTHS = new IntDoubleImmutablePair[] { - IntDoubleImmutablePair.of(1, 1.25), IntDoubleImmutablePair.of(1, 2.25), IntDoubleImmutablePair.of(2, 2.0), - IntDoubleImmutablePair.of(2, 3.0), IntDoubleImmutablePair.of(2, 4.25), IntDoubleImmutablePair.of(3, 2.5), - IntDoubleImmutablePair.of(3, 3.25), IntDoubleImmutablePair.of(3, 4.25), IntDoubleImmutablePair.of(3, 5.5), - IntDoubleImmutablePair.of(4, 3.25), IntDoubleImmutablePair.of(4, 4.0), IntDoubleImmutablePair.of(4, 5.0), - IntDoubleImmutablePair.of(4, 6.0), IntDoubleImmutablePair.of(4, 7.25), IntDoubleImmutablePair.of(4, 8.25), - IntDoubleImmutablePair.of(5, 4.5), IntDoubleImmutablePair.of(5, 5.25), IntDoubleImmutablePair.of(5, 6.25), - IntDoubleImmutablePair.of(5, 7.25), IntDoubleImmutablePair.of(5, 8.5) }; - - private static Shader shaderDown, shaderUp, shaderPassthrough; - private final Framebuffer[] fbos = new Framebuffer[6]; - private final TimerUtils timer = new TimerUtils(); - private boolean firstTick = true; - - public void resize() { for (int i = 0; i < fbos.length; i++) { - if (fbos[i] != null) { - fbos[i].resize(); - } else { - fbos[i] = new Framebuffer(1 / Math.pow(2, i)); - } + fbos[i] = createFbo(i); } } - public void draw(int radius) { + public void draw() { + boolean shouldRender = shouldRender(); + long time = System.currentTimeMillis(); - if (shaderDown == null) { - shaderDown = new Shader("blur.vert", "blur_down.frag"); - shaderUp = new Shader("blur.vert", "blur_up.frag"); - shaderPassthrough = new Shader("passthrough.vert", "passthrough.frag"); - } + if (enabled) { + if (!shouldRender) { + if (fadeEndAt == -1) fadeEndAt = System.currentTimeMillis() + 100; - if (firstTick) { - for (int i = 0; i < fbos.length; i++) { - if (fbos[i] == null) { - fbos[i] = new Framebuffer(1 / Math.pow(2, i)); + if (time >= fadeEndAt) { + enabled = false; + fadeEndAt = -1; } } - firstTick = false; + } else { + if (shouldRender) { + enabled = true; + fadeEndAt = System.currentTimeMillis() + 100; + } } - SystemSettings setting = SystemSettings.getInstance(); + if (!enabled) return; - if(setting.isFastBlur()) { - if (timer.delay(16)) { - timer.reset(); - } else { - return; - } + // Update progress + double progress = 1; + + if (time < fadeEndAt) { + if (shouldRender) progress = 1 - (fadeEndAt - time) / 100f; + else progress = (fadeEndAt - time) / 100f; + } else { + fadeEndAt = -1; } - IntDoubleImmutablePair strength = STRENGTHS[(int) ((radius - 1))]; - int iterations = strength.leftInt(); - double offset = strength.rightDouble(); + // Update strength + int blur_intensity = getBlurIntensity(); - PostProcessRenderer.beginRender(); + IntFloatImmutablePair blur_strength = strengths[(int) ((blur_intensity - 1) * progress)]; + int iterations = blur_strength.leftInt(); + float offset = blur_strength.rightFloat(); - renderToFbo(fbos[0], MinecraftClient.getInstance().getFramebuffer().getColorAttachment(), shaderDown, - offset); + // Update uniforms + if (previousOffset != offset) { + updateUniforms(offset); + previousOffset = offset; + } + + renderToFbo(fbos[0], mc.getMainRenderTarget().getColorTextureView(), PupperRenderPipelines.BLUR_DOWN, ubos[0]); for (int i = 0; i < iterations; i++) { - renderToFbo(fbos[i + 1], fbos[i].texture, shaderDown, offset); + renderToFbo(fbos[i + 1], fbos[i], PupperRenderPipelines.BLUR_DOWN, ubos[i + 1]); } for (int i = iterations; i >= 1; i--) { - renderToFbo(fbos[i - 1], fbos[i].texture, shaderUp, offset); + renderToFbo(fbos[i - 1], fbos[i], PupperRenderPipelines.BLUR_UP, ubos[i - 1]); + } + + PupperMeshRenderer.begin() + .attachments(mc.getMainRenderTarget()) + .pipeline(PupperRenderPipelines.BLUR_PASSTHROUGH) + .fullscreen() + .sampler("u_Texture", fbos[0], RenderSystem.getSamplerCache().getClampToEdge(FilterMode.LINEAR)) // todo ??? + .end(); + } + + private void renderToFbo(GpuTextureView targetFbo, GpuTextureView sourceTexture, RenderPipeline pipeline, GpuBufferSlice ubo) { + PupperMeshRenderer.begin() + .attachments(targetFbo, null) + .pipeline(pipeline) + .fullscreen() + .uniform("BlurData", ubo) + .sampler("u_Texture", sourceTexture, RenderSystem.getSamplerCache().getClampToEdge(FilterMode.LINEAR)) + .end(); + } + + @SuppressWarnings("unused") + public GpuTextureView[] getFbos() { + return fbos; + } + + private GpuTextureView createFbo(int i) { + double scale = 1 / Math.pow(2, i); + + int width = (int) (mc.getWindow().getWidth() * scale); + int height = (int) (mc.getWindow().getHeight() * scale); + + return RenderSystem.getDevice().createTextureView(RenderSystem.getDevice().createTexture("Blur - " + i, 15, TextureFormat.RGBA8, width, height, 1, 1)); + } + + private void rebuildFbos() { + for (int i = 0; i < fbos.length; i++) { + if (fbos[i] != null) { + fbos[i].close(); + } + fbos[i] = createFbo(i); } + previousOffset = -1; + } - MinecraftClient.getInstance().getFramebuffer().beginWrite(true); - shaderPassthrough.bind(); - ShaderHelper.bindTexture(fbos[0].texture); - shaderPassthrough.set("uTexture", 0); - PostProcessRenderer.endRender(); + @EventListener + private void onResolutionChanged(ResolutionChangedEvent event) { + rebuildFbos(); } - public int getTexture() { - return fbos[0].texture; + // Uniforms + private void updateUniforms(float offset) { + UNIFORM_STORAGE.clear(); + + BlurUniformData[] uboData = new BlurUniformData[6]; + for (int i = 0; i < uboData.length; i++) { + GpuTextureView fbo = fbos[i]; + uboData[i] = new BlurUniformData( + 0.5f / fbo.getWidth(0), 0.5f / fbo.getHeight(0), + offset + ); + } + + ubos = UNIFORM_STORAGE.writeAll(uboData); + } + + private static final int UNIFORM_SIZE = new Std140SizeCalculator() + .putVec2() + .putFloat() + .get(); + + private static final FixedUniformStorage UNIFORM_STORAGE = new FixedUniformStorage<>("Meteor - Blur UBO", UNIFORM_SIZE, 6); + + private record BlurUniformData(float halfTexelSizeX, float halfTexelSizeY, float offset) implements DynamicUniformStorage.DynamicUniform { + @Override + public void write(@NonNull ByteBuffer buffer) { + Std140Builder.intoBuffer(buffer) + .putVec2(halfTexelSizeX, halfTexelSizeY) + .putFloat(offset); + } + } + + private int getBlurIntensity() { + if (HUDModSettings.getInstance().getBlurSetting().isEnabled()) { + return (int) ModMenuSettings.getInstance().getBlurIntensitySetting().getValue(); + } + return 5; } - private void renderToFbo(Framebuffer targetFbo, int sourceText, Shader shader, double offset) { - targetFbo.bind(); - targetFbo.setViewport(); - shader.bind(); - ShaderHelper.bindTexture(sourceText); - shader.set("uTexture", 0); - shader.set("uHalfTexelSize", .5 / targetFbo.width, .5 / targetFbo.height); - shader.set("uOffset", offset); - PostProcessRenderer.render(); + private boolean shouldRender() { + return mc.screen instanceof GuiModMenu; } } diff --git a/src/main/java/cn/pupperclient/shader/patch/FixedUniformStorage.java b/src/main/java/cn/pupperclient/shader/patch/FixedUniformStorage.java new file mode 100644 index 0000000..72f52c2 --- /dev/null +++ b/src/main/java/cn/pupperclient/shader/patch/FixedUniformStorage.java @@ -0,0 +1,93 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package cn.pupperclient.shader.patch; + +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.systems.GpuDevice; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.renderer.DynamicUniformStorage; +import net.minecraft.client.renderer.MappableRingBuffer; +import net.minecraft.util.Mth; + +import java.nio.ByteBuffer; + +/** + * UBO storage with a constant size. Exceeding this size causes an {@link IndexOutOfBoundsException} to be thrown. + * + * @author Crosby + * @see DynamicUniformStorage + */ +public class FixedUniformStorage { + private final MappableRingBuffer buffer; + private final int blockSize; + private final int capacity; + private int size; + + public FixedUniformStorage(String name, int blockSize, int capacity) { + GpuDevice gpuDevice = RenderSystem.getDevice(); + this.blockSize = Mth.roundToward(blockSize, gpuDevice.getUniformOffsetAlignment()); + this.capacity = capacity; + int alignedCapacity = Mth.smallestEncompassingPowerOfTwo(capacity); + this.size = 0; + this.buffer = new MappableRingBuffer(() -> name + " x" + this.blockSize, 130, this.blockSize * alignedCapacity); + } + + public GpuBufferSlice write(T value) { + if (this.size >= this.capacity) { + throw new IndexOutOfBoundsException(String.format("Index %s out of bounds for length %s", this.size, this.capacity)); + } else { + int i = this.size * this.blockSize; + GpuBufferSlice slice = this.buffer.currentBuffer().slice(i, this.blockSize); + + try (GpuBuffer.MappedView mappedView = RenderSystem.getDevice() + .createCommandEncoder() + .mapBuffer(slice, false, true)) { + value.write(mappedView.data()); + } + + this.size++; + return slice; + } + } + + public GpuBufferSlice[] writeAll(T[] values) { + if (values.length == 0) { + return new GpuBufferSlice[0]; + } else if (this.size + values.length > this.capacity) { + throw new IndexOutOfBoundsException(String.format("Index %s out of bounds for length %s", this.size + values.length - 1, this.capacity)); + } else { + int i = this.size * this.blockSize; + GpuBufferSlice[] gpuBufferSlices = new GpuBufferSlice[values.length]; + GpuBuffer ubo = this.buffer.currentBuffer(); + + try (GpuBuffer.MappedView mappedView = RenderSystem.getDevice() + .createCommandEncoder() + .mapBuffer(ubo.slice(i, (long) values.length * this.blockSize), false, true)) { + ByteBuffer byteBuffer = mappedView.data(); + + for (int j = 0; j < values.length; j++) { + T uploadable = values[j]; + gpuBufferSlices[j] = ubo.slice(i + (long) j * this.blockSize, this.blockSize); + byteBuffer.position(j * this.blockSize); + uploadable.write(byteBuffer); + } + } + + this.size += values.length; + return gpuBufferSlices; + } + } + + public void clear() { + this.size = 0; + this.buffer.rotate(); + } + + public void close() { + this.buffer.close(); + } +} diff --git a/src/main/java/cn/pupperclient/skia/Skia.java b/src/main/java/cn/pupperclient/skia/Skia.java index f42765e..939632f 100644 --- a/src/main/java/cn/pupperclient/skia/Skia.java +++ b/src/main/java/cn/pupperclient/skia/Skia.java @@ -3,8 +3,8 @@ import java.awt.Color; import java.io.File; +import net.minecraft.resources.Identifier; import cn.pupperclient.management.mod.impl.settings.HUDModSettings; -import cn.pupperclient.shader.impl.Kawaseblur; import cn.pupperclient.skia.context.SkiaContext; import cn.pupperclient.skia.image.ImageHelper; import io.github.humbleui.skija.Canvas; @@ -21,23 +21,50 @@ import io.github.humbleui.types.Point; import io.github.humbleui.types.RRect; import io.github.humbleui.types.Rect; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.util.Window; -import net.minecraft.util.Identifier; +/** + * Skia Graphics Drawing Utility Class + * Provides Skia-based 2D graphics drawing API for Pupper Client UI rendering + * All methods get Canvas through SkiaContext + */ public class Skia { + // Image loading helper for managing textures and image resources private static final ImageHelper imageHelper = new ImageHelper(); + // Shared Paint object to avoid repeated creation and improve performance private static final Paint SHARED_PAINT = new Paint(); + /** + * Draws a filled rectangle with the specified color. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param color The color to fill the rectangle + */ public static void drawRect(float x, float y, float width, float height, Color color) { getCanvas().drawRect(Rect.makeXYWH(x, y, width, height), setupPaint(color)); } + /** + * Draws a filled circle with the specified color. + * @param x The x-coordinate of the circle's center + * @param y The y-coordinate of the circle's center + * @param radius The radius of the circle + * @param color The color to fill the circle + */ public static void drawCircle(float x, float y, float radius, Color color) { getCanvas().drawCircle(x, y, radius, setupPaint(color)); } + /** + * Draws a circle outline with the specified stroke width and color. + * @param x The x-coordinate of the circle's center + * @param y The y-coordinate of the circle's center + * @param radius The radius of the circle + * @param strokeWidth The width of the stroke + * @param color The color of the stroke + */ public static void drawCircle(float x, float y, float radius, float strokeWidth, Color color) { Paint paint = setupPaint(color); paint.setMode(PaintMode.STROKE); @@ -46,10 +73,31 @@ public static void drawCircle(float x, float y, float radius, float strokeWidth, paint.setMode(PaintMode.FILL); // Reset } + /** + * Draws a filled rounded rectangle with the specified radius and color. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param radius The corner radius + * @param color The color to fill the rectangle + */ public static void drawRoundedRect(float x, float y, float width, float height, float radius, Color color) { getCanvas().drawRRect(RRect.makeXYWH(x, y, width, height, radius), setupPaint(color)); } + /** + * Draws a filled rounded rectangle with varying corner radii. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param topLeft The top-left corner radius + * @param topRight The top-right corner radius + * @param bottomRight The bottom-right corner radius + * @param bottomLeft The bottom-left corner radius + * @param color The color to fill the rectangle + */ public static void drawRoundedRectVarying(float x, float y, float width, float height, float topLeft, float topRight, float bottomRight, float bottomLeft, Color color) { @@ -59,36 +107,46 @@ public static void drawRoundedRectVarying(float x, float y, float width, float h getCanvas().drawRRect(RRect.makeComplexXYWH(x, y, width, height, corners), setupPaint(color)); } + // TODO: fix Draw Blur Texture in anywhere public static void drawBlur(float x, float y, float width, float height) { if (HUDModSettings.getInstance().getBlurSetting().isEnabled()) { - Window window = MinecraftClient.getInstance().getWindow(); - try (Path path = Path.makeRect(Rect.makeXYWH(x, y, width, height))) { - save(); - getCanvas().clipPath(path, ClipMode.INTERSECT, true); - drawImage(Kawaseblur.INGAME_BLUR.getTexture(), 0, 0, window.getScaledWidth(), window.getScaledHeight(), 1F, - SurfaceOrigin.BOTTOM_LEFT); - restore(); - } +// Window window = Minecraft.getInstance().getWindow(); +// try (Path path = Path.makeRect(Rect.makeXYWH(x, y, width, height))) { +// save(); +// getCanvas().clipPath(path, ClipMode.INTERSECT, true); +// drawImage(Kawaseblur.INGAME_BLUR.getTexture(), 0, 0, window.getGuiScaledWidth(), window.getGuiScaledHeight(), 1F, +// SurfaceOrigin.BOTTOM_LEFT); +// restore(); +// } } } + // TODO: fix Draw Blur Texture in anywhere public static void drawRoundedBlur(float x, float y, float width, float height, float radius) { if (HUDModSettings.getInstance().getBlurSetting().isEnabled()) { - Window window = MinecraftClient.getInstance().getWindow(); - try (Path path = Path.makeRRect(RRect.makeXYWH(x, y, width, height, radius))) { - save(); - getCanvas().clipPath(path, ClipMode.INTERSECT, true); - drawImage(Kawaseblur.INGAME_BLUR.getTexture(), 0, 0, window.getScaledWidth(), window.getScaledHeight(), 1F, - SurfaceOrigin.BOTTOM_LEFT); - restore(); - } +// Window window = Minecraft.getInstance().getWindow(); +// try (Path path = Path.makeRRect(RRect.makeXYWH(x, y, width, height, radius))) { +// save(); +// getCanvas().clipPath(path, ClipMode.INTERSECT, true); +// drawImage(Kawaseblur.INGAME_BLUR.getTexture(), 0, 0, window.getGuiScaledWidth(), window.getGuiScaledHeight(), 1F, +// SurfaceOrigin.BOTTOM_LEFT); +// restore(); +// } } } + /** + * Draws a drop shadow effect behind a rounded rectangle. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param radius The corner radius + */ public static void drawShadow(float x, float y, float width, float height, float radius) { try (Paint paint = new Paint(); @@ -104,6 +162,16 @@ public static void drawShadow(float x, float y, float width, float height, float } } + /** + * Draws an outline (stroke) around a rounded rectangle. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param radius The corner radius + * @param strokeWidth The width of the outline stroke + * @param color The color of the outline + */ public static void drawOutline(float x, float y, float width, float height, float radius, float strokeWidth, Color color) { @@ -121,6 +189,14 @@ public static void drawOutline(float x, float y, float width, float height, floa } } + /** + * Draws an image from the assets/pupper/ directory. + * @param path The path to the image file relative to assets/pupper/ + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + */ public static void drawImage(String path, float x, float y, float width, float height) { path = "/assets/pupper/" + path; @@ -130,6 +206,16 @@ public static void drawImage(String path, float x, float y, float width, float h } } + /** + * Draws an image from a texture ID with specified alpha and origin. + * @param textureId The OpenGL texture ID + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + * @param alpha The alpha transparency (0.0 to 1.0) + * @param origin The surface origin for the image + */ public static void drawImage(int textureId, float x, float y, float width, float height, float alpha, SurfaceOrigin origin) { @@ -141,16 +227,42 @@ public static void drawImage(int textureId, float x, float y, float width, float } } + /** + * Draws an image from a texture ID with specified alpha (default origin TOP_LEFT). + * @param textureId The OpenGL texture ID + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + * @param alpha The alpha transparency (0.0 to 1.0) + */ public static void drawImage(int textureId, float x, float y, float width, float height, float alpha) { drawImage(textureId, x, y, width, height, alpha, SurfaceOrigin.TOP_LEFT); } + /** + * Draws an image from a file. + * @param file The image file + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + */ public static void drawImage(File file, float x, float y, float width, float height) { if (imageHelper.load(file)) { getCanvas().drawImageRect(imageHelper.get(file.getName()), Rect.makeXYWH(x, y, width, height)); } } + /** + * Draws an image from a texture ID with specified origin. + * @param textureId The OpenGL texture ID + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + * @param origin The surface origin for the image + */ public static void drawImage(int textureId, float x, float y, float width, float height, SurfaceOrigin origin) { if (imageHelper.load(textureId, width, height, origin)) { @@ -158,10 +270,27 @@ public static void drawImage(int textureId, float x, float y, float width, float } } + /** + * Draws an image from a texture ID (default origin TOP_LEFT). + * @param textureId The OpenGL texture ID + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + */ public static void drawImage(int textureId, float x, float y, float width, float height) { drawImage(textureId, x, y, width, height, SurfaceOrigin.TOP_LEFT); } + /** + * Draws a rounded image from a texture ID. + * @param textureId The OpenGL texture ID + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + * @param radius The corner radius for clipping + */ public static void drawRoundedImage(int textureId, float x, float y, float width, float height, float radius) { try (Path path = Path.makeRRect(RRect.makeXYWH(x, y, width, height, radius))) { @@ -172,6 +301,15 @@ public static void drawRoundedImage(int textureId, float x, float y, float width } } + /** + * Draws a rounded image from a file path. + * @param filePath The path to the image file + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + * @param radius The corner radius for clipping + */ public static void drawRoundedImage(String filePath, float x, float y, float width, float height, float radius) { try (Path path = Path.makeRRect(RRect.makeXYWH(x, y, width, height, radius))) { @@ -182,6 +320,15 @@ public static void drawRoundedImage(String filePath, float x, float y, float wid } } + /** + * Draws a rounded image from a file. + * @param file The image file + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + * @param radius The corner radius for clipping + */ public static void drawRoundedImage(File file, float x, float y, float width, float height, float radius) { try (Path path = Path.makeRRect(RRect.makeXYWH(x, y, width, height, radius))) { @@ -192,6 +339,17 @@ public static void drawRoundedImage(File file, float x, float y, float width, fl } } + /** + * Draws a rounded image from a texture ID with alpha and origin. + * @param textureId The OpenGL texture ID + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + * @param radius The corner radius for clipping + * @param alpha The alpha transparency (0.0 to 1.0) + * @param origin The surface origin for the image + */ public static void drawRoundedImage(int textureId, float x, float y, float width, float height, float radius, float alpha, SurfaceOrigin origin) { try (Path path = Path.makeRRect(RRect.makeXYWH(x, y, width, height, radius))) { @@ -202,11 +360,30 @@ public static void drawRoundedImage(int textureId, float x, float y, float width } } + /** + * Draws a rounded image from a texture ID with alpha (default origin TOP_LEFT). + * @param textureId The OpenGL texture ID + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + * @param radius The corner radius for clipping + * @param alpha The alpha transparency (0.0 to 1.0) + */ public static void drawRoundedImage(int textureId, float x, float y, float width, float height, float radius, float alpha) { drawRoundedImage(textureId, x, y, width, height, radius, alpha, SurfaceOrigin.TOP_LEFT); } + /** + * Draws a player's head from a skin file with rounded corners. + * @param file The skin file + * @param x The x-coordinate of the head's top-left corner + * @param y The y-coordinate of the head's top-left corner + * @param width The width to draw the head + * @param height The height to draw the head + * @param radius The corner radius for clipping + */ public static void drawPlayerHead(File file, float x, float y, float width, float height, float radius) { if (imageHelper.load(file)) { @@ -224,6 +401,13 @@ public static void drawPlayerHead(File file, float x, float y, float width, floa } } + /** + * Draws a full player skin at the specified position and scale. + * @param file The skin file + * @param x The x-coordinate of the skin's top-left corner + * @param y The y-coordinate of the skin's top-left corner + * @param scale The scale factor for the skin + */ public static void drawSkin(File file, float x, float y, float scale) { if (imageHelper.load(file)) { @@ -286,14 +470,33 @@ public static void drawSkin(File file, float x, float y, float scale) { restore(); } } + + /** + * Draws an image from Minecraft's resources. + * @param path The path to the image in Minecraft's namespace + * @param x The x-coordinate of the image's top-left corner + * @param y The y-coordinate of the image's top-left corner + * @param width The width to draw the image + * @param height The height to draw the image + */ public static void drawMinecraftImage(String path, float x, float y, float width, float height) { - Identifier identifier = Identifier.of("minecraft", path); + Identifier identifier = Identifier.fromNamespaceAndPath("minecraft", path); if (imageHelper.load(identifier)) { - getCanvas().drawImageRect(imageHelper.get(identifier.getPath()), Rect.makeXYWH(x, y, width, height)); + getCanvas().drawImageRect(imageHelper.get(identifier.toString()), Rect.makeXYWH(x, y, width, height)); } } + /** + * Draws an arc (partial circle outline) with the specified parameters. + * @param x The x-coordinate of the arc's center + * @param y The y-coordinate of the arc's center + * @param radius The radius of the arc + * @param startAngle The starting angle in degrees + * @param endAngle The ending angle in degrees + * @param strokeWidth The width of the arc stroke + * @param color The color of the arc + */ public static void drawArc(float x, float y, float radius, float startAngle, float endAngle, float strokeWidth, Color color) { @@ -305,6 +508,15 @@ public static void drawArc(float x, float y, float radius, float startAngle, flo paint.setMode(PaintMode.FILL); // Reset } + /** + * Draws a line between two points with the specified width and color. + * @param x The x-coordinate of the starting point + * @param y The y-coordinate of the starting point + * @param endX The x-coordinate of the ending point + * @param endY The y-coordinate of the ending point + * @param width The width of the line + * @param color The color of the line + */ public static void drawLine(float x, float y, float endX, float endY, float width, Color color) { Paint paint = setupPaint(color); @@ -317,6 +529,16 @@ public static void drawLine(float x, float y, float endX, float endY, float widt paint.setStroke(false); // Reset } + /** + * Draws a rounded rectangle with an animated gradient fill. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param radius The corner radius + * @param color1 The first color of the gradient + * @param color2 The second color of the gradient + */ public static void drawGradientRoundedRect(float x, float y, float width, float height, float radius, Color color1, Color color2) { @@ -350,14 +572,33 @@ public static void drawGradientRoundedRect(float x, float y, float width, float } } + /** + * Clips the drawing area to the specified path. + * @param path The path to clip to + * @param mode The clipping mode + * @param arg Additional clipping argument + */ public static void clipPath(Path path, ClipMode mode, boolean arg) { getCanvas().clipPath(path, mode, arg); } + /** + * Clips the drawing area to the specified path (default intersect mode). + * @param path The path to clip to + */ public static void clipPath(Path path) { getCanvas().clipPath(path, ClipMode.INTERSECT, true); } + /** + * Clips the drawing area to a rounded rectangle. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param radius The corner radius + * @param mode The clipping mode + */ public static void clip(float x, float y, float width, float height, float radius, ClipMode mode) { try (Path path = Path.makeRRect(RRect.makeXYWH(x, y, width, height, radius))) { @@ -365,6 +606,17 @@ public static void clip(float x, float y, float width, float height, float radiu } } + /** + * Clips the drawing area to a rounded rectangle with varying corner radii. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param topLeft The top-left corner radius + * @param topRight The top-right corner radius + * @param bottomRight The bottom-right corner radius + * @param bottomLeft The bottom-left corner radius + */ public static void clip(float x, float y, float width, float height, float topLeft, float topRight, float bottomRight, float bottomLeft) { @@ -376,21 +628,53 @@ public static void clip(float x, float y, float width, float height, float topLe } } + /** + * Clips the drawing area to a rounded rectangle (default intersect mode). + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param radius The corner radius + */ public static void clip(float x, float y, float width, float height, float radius) { clip(x, y, width, height, radius, ClipMode.INTERSECT); } + /** + * Draws text at the specified position. + * @param text The text to draw + * @param x The x-coordinate of the text's baseline start + * @param y The y-coordinate of the text's baseline + * @param color The color of the text + * @param font The font to use + */ public static void drawText(String text, float x, float y, Color color, Font font) { Rect bounds = font.measureText(text); getCanvas().drawString(text, x - bounds.getLeft(), y - bounds.getTop(), font, setupPaint(color)); } + /** + * Draws text centered horizontally at the specified position. + * @param text The text to draw + * @param x The x-coordinate of the text's center + * @param y The y-coordinate of the text's baseline + * @param color The color of the text + * @param font The font to use + */ public static void drawCenteredText(String text, float x, float y, Color color, Font font) { Rect bounds = font.measureText(text); getCanvas().drawString(text, x - bounds.getLeft() - (bounds.getWidth() / 2), y - bounds.getTop(), font, setupPaint(color)); } + /** + * Draws text centered vertically at the specified position. + * @param text The text to draw + * @param x The x-coordinate of the text's baseline start + * @param y The y-coordinate of the text's vertical center + * @param color The color of the text + * @param font The font to use + */ public static void drawHeightCenteredText(String text, float x, float y, Color color, Font font) { FontMetrics metrics = font.getMetrics(); @@ -401,6 +685,14 @@ public static void drawHeightCenteredText(String text, float x, float y, Color c getCanvas().drawString(text, x - bounds.getLeft(), textCenterY, font, setupPaint(color)); } + /** + * Draws text centered both horizontally and vertically at the specified position. + * @param text The text to draw + * @param x The x-coordinate of the text's center + * @param y The y-coordinate of the text's vertical center + * @param color The color of the text + * @param font The font to use + */ public static void drawFullCenteredText(String text, float x, float y, Color color, Font font) { Rect bounds = font.measureText(text); @@ -413,10 +705,23 @@ public static void drawFullCenteredText(String text, float x, float y, Color col getCanvas().drawString(text, textCenterX, textCenterY, font, setupPaint(color)); } + /** + * Gets the bounding rectangle of the specified text with the given font. + * @param text The text to measure + * @param font The font to use + * @return The bounding rectangle of the text + */ public static Rect getTextBounds(String text, Font font) { return font.measureText(text); } + /** + * Truncates text to fit within the specified width, adding ellipsis if necessary. + * @param text The original text + * @param font The font to use + * @param width The maximum width + * @return The truncated text with ellipsis if needed + */ public static String getLimitText(String text, Font font, float width) { boolean isInRange = false; @@ -435,29 +740,58 @@ public static String getLimitText(String text, Font font, float width) { return text + (isRemoved ? "..." : ""); } + /** + * Sets up a Paint object with the specified color. + * @param color The color to set + * @return The configured Paint object + */ public static Paint setupPaint(Color color) { SHARED_PAINT.setARGB(color.getAlpha(), color.getRed(), color.getGreen(), color.getBlue()); return SHARED_PAINT; } + /** + * Saves the current canvas state (transformation matrix, clip, etc.). + */ public static void save() { getCanvas().save(); } + /** + * Restores the previously saved canvas state. + */ public static void restore() { getCanvas().restore(); } + /** + * Scales the canvas by the specified factor from the origin. + * @param scale The scale factor + */ public static void scale(float scale) { getCanvas().scale(scale, scale); } + /** + * Scales the canvas by the specified factor from the specified point. + * @param x The x-coordinate of the scaling center + * @param y The y-coordinate of the scaling center + * @param scale The scale factor + */ public static void scale(float x, float y, float scale) { getCanvas().translate(x, y); getCanvas().scale(scale, scale); getCanvas().translate(-x, -y); } + /** + * Scales the canvas by the specified factor from the center of the given rectangle. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param scale The scale factor + */ public static void scale(float x, float y, float width, float height, float scale) { float centerX = x + width / 2; @@ -468,10 +802,23 @@ public static void scale(float x, float y, float width, float height, float scal getCanvas().translate(-centerX, -centerY); } + /** + * Translates (moves) the canvas by the specified offset. + * @param x The x-offset + * @param y The y-offset + */ public static void translate(float x, float y) { getCanvas().translate(x, y); } + /** + * Rotates the canvas by the specified angle around the center of the given rectangle. + * @param x The x-coordinate of the rectangle's top-left corner + * @param y The y-coordinate of the rectangle's top-left corner + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param rotate The rotation angle in degrees + */ public static void rotate(float x, float y, float width, float height, float rotate) { float centerX = x + width / 2; @@ -482,6 +829,10 @@ public static void rotate(float x, float y, float width, float height, float rot getCanvas().translate(-centerX, -centerY); } + /** + * Sets the global alpha (transparency) for subsequent drawing operations. + * @param alpha The alpha value (0-255) + */ public static void setAlpha(int alpha) { try (Paint paint = new Paint()) { paint.setAlpha(alpha); @@ -489,10 +840,18 @@ public static void setAlpha(int alpha) { } } + /** + * Gets the current Skia Canvas for drawing. + * @return The Skia Canvas object + */ public static Canvas getCanvas() { return SkiaContext.getCanvas(); } + /** + * Gets the ImageHelper instance for managing images and textures. + * @return The ImageHelper instance + */ public static ImageHelper getImageHelper() { return imageHelper; } diff --git a/src/main/java/cn/pupperclient/skia/api/WrappedBackendRenderTarget.java b/src/main/java/cn/pupperclient/skia/api/WrappedBackendRenderTarget.java new file mode 100644 index 0000000..ddba3e9 --- /dev/null +++ b/src/main/java/cn/pupperclient/skia/api/WrappedBackendRenderTarget.java @@ -0,0 +1,69 @@ +package cn.pupperclient.skia.api; + +import io.github.humbleui.skija.BackendRenderTarget; +import io.github.humbleui.skija.impl.Stats; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +/** + * @Author: oneachina + * @Date: 2026/2/3 11:18 + */ +public class WrappedBackendRenderTarget extends BackendRenderTarget { + private final int width; + private final int height; + private final int sampleCnt; + private final int stencilBits; + private final int fbId; + private final int fbFormat; + + public WrappedBackendRenderTarget( + int width, + int height, + int sampleCnt, + int stencilBits, + int fbId, + int fbFormat, + long ptr + ) { + super(ptr); + this.width = width; + this.height = height; + this.sampleCnt = sampleCnt; + this.stencilBits = stencilBits; + this.fbId = fbId; + this.fbFormat = fbFormat; + } + + /** + * @see BackendRenderTarget#makeGL(int, int, int, int, int, int) + */ + @Contract("_, _, _, _, _, _ -> new") + public static @NotNull WrappedBackendRenderTarget makeGL( + int width, + int height, + int sampleCnt, + int stencilBits, + int fbId, + int fbFormat + ) { + Stats.onNativeCall(); + return new WrappedBackendRenderTarget( + width, + height, + sampleCnt, + stencilBits, + fbId, + fbFormat, + _nMakeGL(width, height, sampleCnt, stencilBits, fbId, fbFormat) + ); + } + + // Getters + public int getWidth() { return width; } + public int getHeight() { return height; } + public int getSampleCnt() { return sampleCnt; } + public int getStencilBits() { return stencilBits; } + public int getFbId() { return fbId; } + public int getFbFormat() { return fbFormat; } +} diff --git a/src/main/java/cn/pupperclient/skia/context/SkiaContext.java b/src/main/java/cn/pupperclient/skia/context/SkiaContext.java index 27acae6..27f3044 100644 --- a/src/main/java/cn/pupperclient/skia/context/SkiaContext.java +++ b/src/main/java/cn/pupperclient/skia/context/SkiaContext.java @@ -1,92 +1,112 @@ package cn.pupperclient.skia.context; +import java.util.Objects; import java.util.function.Consumer; +import cn.pupperclient.PupperLogger; +import cn.pupperclient.skia.api.WrappedBackendRenderTarget; +import cn.pupperclient.skia.gl.States; +import io.github.humbleui.skija.*; + import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL13; -import org.lwjgl.opengl.GL33; - -import com.mojang.blaze3d.platform.GlConst; -import com.mojang.blaze3d.systems.RenderSystem; - -import io.github.humbleui.skija.BackendRenderTarget; -import io.github.humbleui.skija.Canvas; -import io.github.humbleui.skija.ColorSpace; -import io.github.humbleui.skija.DirectContext; -import io.github.humbleui.skija.Surface; -import io.github.humbleui.skija.SurfaceColorFormat; -import io.github.humbleui.skija.SurfaceOrigin; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.BufferRenderer; +import org.lwjgl.opengl.GL30; +/** + * Skia rendering context manager for Pupper Client. + * Handles Skia DirectContext, Surface, and BackendRenderTarget creation and drawing. + */ public class SkiaContext { - - private static DirectContext context = null; - private static Surface surface; - private static BackendRenderTarget renderTarget; - + private static DirectContext context = null; // Skia GPU context + private static Surface surface; // Skia drawing surface + private static WrappedBackendRenderTarget renderTarget; // Backend render target for GL + + /** + * Gets the current Skia canvas for drawing. + * @return The Skia Canvas object, or null if surface is not initialized. + */ public static Canvas getCanvas() { return surface.getCanvas(); } - public static void createSurface(int width, int height) { - + /** + * Creates or recreates the Skia surface with the given dimensions. + * This should be called when the window size changes. + * @param width The width of the surface in pixels. + * @param height The height of the surface in pixels. + * @param fboid framebuffer object id, if 0 or null, will use currently bound framebuffer + */ + public static void createSurface(int width, int height, Integer fboid) { + // Initialize Skia DirectContext if not already done if (context == null) { context = DirectContext.makeGL(); } - if (surface != null) { - surface.close(); - surface = null; - } - - if (renderTarget != null) { - renderTarget.close(); - renderTarget = null; + // Clean up existing surface and render target + if (surface != null) surface.close(); + if (renderTarget != null) renderTarget.close(); + + try { + // Get current framebuffer binding + int currentFbo = fboid == null || fboid == 0 ? GL11.glGetInteger(GL30.GL_FRAMEBUFFER_BINDING) : fboid; + + // Create GL backend render target using current framebuffer + renderTarget = WrappedBackendRenderTarget.makeGL( + width, + height, + 0, // sample count + 8, // stencil bits + currentFbo, // framebuffer ID (use current) + FramebufferFormat.GR_GL_RGBA8 // RGBA8 format + ); + + // Wrap the render target into a Skia surface + surface = Surface.wrapBackendRenderTarget( + Objects.requireNonNull(context, "Context must not be null"), + Objects.requireNonNull(renderTarget, "RenderTarget must not be null"), + SurfaceOrigin.BOTTOM_LEFT, // Origin for GL + ColorType.RGBA_8888, // Color format + ColorSpace.getSRGB() // sRGB color space + ); + + PupperLogger.info("Skia", "Created surface with fbo=" + currentFbo + ", size=" + width + "x" + height); + } catch (Exception e) { + PupperLogger.error("Skia", "Failed to create Skia surface: ", e); } - - renderTarget = BackendRenderTarget.makeGL(width, height, 0, 8, - MinecraftClient.getInstance().getFramebuffer().fbo, GL11.GL_RGBA8); - surface = Surface.wrapBackendRenderTarget(context, renderTarget, SurfaceOrigin.BOTTOM_LEFT, - SurfaceColorFormat.RGBA_8888, ColorSpace.getSRGB()); } + /** + * Performs Skia drawing operations. + * Pushes GL states, resets Skia context, executes drawing logic, and submits to GL. + * @param drawingLogic A consumer that takes a Canvas and performs drawing operations. + */ public static void draw(Consumer drawingLogic) { + if (context == null || surface == null) { + PupperLogger.warn("Skia", "Context or surface is null, skipping draw"); + return; + } - RenderSystem.pixelStore(GlConst.GL_UNPACK_ROW_LENGTH, 0); - RenderSystem.pixelStore(GlConst.GL_UNPACK_SKIP_PIXELS, 0); - RenderSystem.pixelStore(GlConst.GL_UNPACK_SKIP_ROWS, 0); - RenderSystem.pixelStore(GlConst.GL_UNPACK_ALIGNMENT, 4); - RenderSystem.clearColor(0f, 0f, 0f, 0f); + if (renderTarget == null) { + PupperLogger.warn("Skia", "RenderTarget is null, skipping draw"); + return; + } + + States.push(); + GL11.glDisable(GL11.GL_CULL_FACE); + GL11.glClearColor(0f, 0f, 0f, 0f); context.resetGLAll(); Canvas canvas = getCanvas(); drawingLogic.accept(canvas); - context.flush(); - - BufferRenderer.reset(); - GL33.glBindSampler(0, 0); - RenderSystem.disableBlend(); - GL11.glDisable(GL11.GL_BLEND); - RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); - GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); - RenderSystem.blendEquation(GL33.GL_FUNC_ADD); - GL33.glBlendEquation(GL33.GL_FUNC_ADD); - RenderSystem.colorMask(true, true, true, true); - GL11.glColorMask(true, true, true, true); - RenderSystem.depthMask(true); - GL11.glDepthMask(true); - RenderSystem.disableScissor(); - GL11.glDisable(GL11.GL_SCISSOR_TEST); - GL11.glDisable(GL11.GL_STENCIL_TEST); - RenderSystem.disableDepthTest(); - GL11.glDisable(GL11.GL_DEPTH_TEST); - GL13.glActiveTexture(GL13.GL_TEXTURE0); - RenderSystem.activeTexture(GL13.GL_TEXTURE0); - RenderSystem.disableCull(); + context.flushAndSubmit(surface); + + States.pop(); } + /** + * Gets the current Skia DirectContext. + * @return The DirectContext, or null if not initialized. + */ public static DirectContext getContext() { return context; } diff --git a/src/main/java/cn/pupperclient/skia/gl/Properties.java b/src/main/java/cn/pupperclient/skia/gl/Properties.java new file mode 100644 index 0000000..6f8555d --- /dev/null +++ b/src/main/java/cn/pupperclient/skia/gl/Properties.java @@ -0,0 +1,80 @@ +/* + * This file is part of https://github.com/Lyzev/Skija. + * + * Copyright (c) 2025. Lyzev + * + * Skija is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3 of the License, or + * (at your option) any later version. + */ + +package cn.pupperclient.skia.gl; + +import java.util.BitSet; + +/* + * Converted to Java by oneachina + */ +public class Properties { + + public final int[] lastActiveTexture = new int[1]; + public final int[] lastFramebuffer = new int[1]; + public final int[] lastProgram = new int[1]; + public final int[] lastTexture = new int[1]; + public final int[] lastSampler = new int[1]; + public final int[] lastArrayBuffer = new int[1]; + public final int[] lastVertexArrayObject = new int[1]; + public final int[] lastPolygonMode = new int[2]; + public final int[] lastViewport = new int[4]; + public final int[] lastScissorBox = new int[4]; + public final int[] lastBlendSrcRgb = new int[1]; + public final int[] lastBlendDstRgb = new int[1]; + public final int[] lastBlendSrcAlpha = new int[1]; + public final int[] lastBlendDstAlpha = new int[1]; + public final int[] lastBlendEquationRgb = new int[1]; + public final int[] lastBlendEquationAlpha = new int[1]; + + public final int[] lastPixelUnpackBufferBinding = new int[1]; + public final int[] lastUnpackAlignment = new int[1]; + public final int[] lastUnpackRowLength = new int[1]; + public final int[] lastUnpackSkipPixels = new int[1]; + public final int[] lastUnpackSkipRows = new int[1]; + public final int[] lastPackSwapBytes = new int[1]; + public final int[] lastPackLsbFirst = new int[1]; + public final int[] lastPackRowLength = new int[1]; + public final int[] lastPackImageHeight = new int[1]; + public final int[] lastPackSkipPixels = new int[1]; + public final int[] lastPackSkipRows = new int[1]; + public final int[] lastPackSkipImages = new int[1]; + public final int[] lastPackAlignment = new int[1]; + public final int[] lastUnpackSwapBytes = new int[1]; + public final int[] lastUnpackLsbFirst = new int[1]; + public final int[] lastUnpackImageHeight = new int[1]; + public final int[] lastUnpackSkipImages = new int[1]; + + private final BitSet flags = new BitSet(7); + + // Boolean Properties via BitSet + + public boolean isLastEnableBlend() { return flags.get(0); } + public void setLastEnableBlend(boolean value) { flags.set(0, value); } + + public boolean isLastEnableCullFace() { return flags.get(1); } + public void setLastEnableCullFace(boolean value) { flags.set(1, value); } + + public boolean isLastEnableDepthTest() { return flags.get(2); } + public void setLastEnableDepthTest(boolean value) { flags.set(2, value); } + + public boolean isLastEnableStencilTest() { return flags.get(3); } + public void setLastEnableStencilTest(boolean value) { flags.set(3, value); } + + public boolean isLastEnableScissorTest() { return flags.get(4); } + public void setLastEnableScissorTest(boolean value) { flags.set(4, value); } + + public boolean isLastEnablePrimitiveRestart() { return flags.get(5); } + public void setLastEnablePrimitiveRestart(boolean value) { flags.set(5, value); } + + public boolean isLastDepthMask() { return flags.get(6); } + public void setLastDepthMask(boolean value) { flags.set(6, value); } +} diff --git a/src/main/java/cn/pupperclient/skia/gl/State.java b/src/main/java/cn/pupperclient/skia/gl/State.java new file mode 100644 index 0000000..4e44a4f --- /dev/null +++ b/src/main/java/cn/pupperclient/skia/gl/State.java @@ -0,0 +1,196 @@ +/* + * Hina Client + * Copyright (C) 2026 Hina Client + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * This file is part of https://github.com/Lyzev/Skija. + * + * Copyright (c) 2025. Lyzev + * + * Skija is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3 of the License, or + * (at your option) any later version. + */ + +/* + * Converted to Java by oneachina + */ + +package cn.pupperclient.skia.gl; + +import org.lwjgl.opengl.GL; +import static org.lwjgl.opengl.GL45.*; + +/** + * Represents the OpenGL state. + */ +public class State { + private final int glVersion; + private final Properties props = new Properties(); + + public State(int glVersion) { + this.glVersion = glVersion; + } + + /** + * Saves the current OpenGL state. + * + * @see #pop() + */ + public State push() { + glGetIntegerv(GL_ACTIVE_TEXTURE, props.lastActiveTexture); + glGetIntegerv(GL_FRAMEBUFFER_BINDING, props.lastFramebuffer); + glActiveTexture(GL_TEXTURE0); + glGetIntegerv(GL_CURRENT_PROGRAM, props.lastProgram); + glGetIntegerv(GL_TEXTURE_BINDING_2D, props.lastTexture); + + if (glVersion >= 330 || GL.getCapabilities().GL_ARB_sampler_objects) { + glGetIntegerv(GL_SAMPLER_BINDING, props.lastSampler); + } + + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, props.lastArrayBuffer); + glGetIntegerv(GL_VERTEX_ARRAY_BINDING, props.lastVertexArrayObject); + + if (glVersion >= 200) { + glGetIntegerv(GL_POLYGON_MODE, props.lastPolygonMode); + } + + glGetIntegerv(GL_VIEWPORT, props.lastViewport); + glGetIntegerv(GL_SCISSOR_BOX, props.lastScissorBox); + glGetIntegerv(GL_BLEND_SRC_RGB, props.lastBlendSrcRgb); + glGetIntegerv(GL_BLEND_DST_RGB, props.lastBlendDstRgb); + glGetIntegerv(GL_BLEND_SRC_ALPHA, props.lastBlendSrcAlpha); + glGetIntegerv(GL_BLEND_DST_ALPHA, props.lastBlendDstAlpha); + glGetIntegerv(GL_BLEND_EQUATION_RGB, props.lastBlendEquationRgb); + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, props.lastBlendEquationAlpha); + + props.setLastEnableBlend(glIsEnabled(GL_BLEND)); + props.setLastEnableCullFace(glIsEnabled(GL_CULL_FACE)); + props.setLastEnableDepthTest(glIsEnabled(GL_DEPTH_TEST)); + props.setLastEnableStencilTest(glIsEnabled(GL_STENCIL_TEST)); + props.setLastEnableScissorTest(glIsEnabled(GL_SCISSOR_TEST)); + + if (glVersion >= 310) { + props.setLastEnablePrimitiveRestart(glIsEnabled(GL_PRIMITIVE_RESTART)); + } + + props.setLastDepthMask(glGetBoolean(GL_DEPTH_WRITEMASK)); + + glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, props.lastPixelUnpackBufferBinding); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + glGetIntegerv(GL_PACK_SWAP_BYTES, props.lastPackSwapBytes); + glGetIntegerv(GL_PACK_LSB_FIRST, props.lastPackLsbFirst); + glGetIntegerv(GL_PACK_ROW_LENGTH, props.lastPackRowLength); + glGetIntegerv(GL_PACK_SKIP_PIXELS, props.lastPackSkipPixels); + glGetIntegerv(GL_PACK_SKIP_ROWS, props.lastPackSkipRows); + glGetIntegerv(GL_PACK_ALIGNMENT, props.lastPackAlignment); + + glGetIntegerv(GL_UNPACK_SWAP_BYTES, props.lastUnpackSwapBytes); + glGetIntegerv(GL_UNPACK_LSB_FIRST, props.lastUnpackLsbFirst); + glGetIntegerv(GL_UNPACK_ALIGNMENT, props.lastUnpackAlignment); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, props.lastUnpackRowLength); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, props.lastUnpackSkipPixels); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, props.lastUnpackSkipRows); + + if (glVersion >= 120) { + glGetIntegerv(GL_PACK_IMAGE_HEIGHT, props.lastPackImageHeight); + glGetIntegerv(GL_PACK_SKIP_IMAGES, props.lastPackSkipImages); + glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, props.lastUnpackImageHeight); + glGetIntegerv(GL_UNPACK_SKIP_IMAGES, props.lastUnpackSkipImages); + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + + return this; + } + + /** + * Restores the state that was saved with {@link #push()}. + * + * @see #push() + */ + public State pop() { + glUseProgram(props.lastProgram[0]); + glBindTexture(GL_TEXTURE_2D, props.lastTexture[0]); + + if (glVersion >= 330 || GL.getCapabilities().GL_ARB_sampler_objects) { + glBindSampler(0, props.lastSampler[0]); + } + + glActiveTexture(props.lastActiveTexture[0]); + glBindFramebuffer(GL_FRAMEBUFFER, props.lastFramebuffer[0]); + glBindVertexArray(props.lastVertexArrayObject[0]); + glBindBuffer(GL_ARRAY_BUFFER, props.lastArrayBuffer[0]); + + glBlendEquationSeparate(props.lastBlendEquationRgb[0], props.lastBlendEquationAlpha[0]); + glBlendFuncSeparate( + props.lastBlendSrcRgb[0], + props.lastBlendDstRgb[0], + props.lastBlendSrcAlpha[0], + props.lastBlendDstAlpha[0] + ); + + if (props.isLastEnableBlend()) glEnable(GL_BLEND); else glDisable(GL_BLEND); + if (props.isLastEnableCullFace()) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); + if (props.isLastEnableDepthTest()) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); + if (props.isLastEnableStencilTest()) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST); + if (props.isLastEnableScissorTest()) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); + + if (glVersion >= 310) { + if (props.isLastEnablePrimitiveRestart()) glEnable(GL_PRIMITIVE_RESTART); + else glDisable(GL_PRIMITIVE_RESTART); + } + + if (glVersion >= 200) { + glPolygonMode(GL_FRONT_AND_BACK, props.lastPolygonMode[0]); + } + + glViewport(props.lastViewport[0], props.lastViewport[1], props.lastViewport[2], props.lastViewport[3]); + glScissor(props.lastScissorBox[0], props.lastScissorBox[1], props.lastScissorBox[2], props.lastScissorBox[3]); + + glPixelStorei(GL_PACK_SWAP_BYTES, props.lastPackSwapBytes[0]); + glPixelStorei(GL_PACK_LSB_FIRST, props.lastPackLsbFirst[0]); + glPixelStorei(GL_PACK_ROW_LENGTH, props.lastPackRowLength[0]); + glPixelStorei(GL_PACK_SKIP_PIXELS, props.lastPackSkipPixels[0]); + glPixelStorei(GL_PACK_SKIP_ROWS, props.lastPackSkipRows[0]); + glPixelStorei(GL_PACK_ALIGNMENT, props.lastPackAlignment[0]); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, props.lastPixelUnpackBufferBinding[0]); + glPixelStorei(GL_UNPACK_SWAP_BYTES, props.lastUnpackSwapBytes[0]); + glPixelStorei(GL_UNPACK_LSB_FIRST, props.lastUnpackLsbFirst[0]); + glPixelStorei(GL_UNPACK_ALIGNMENT, props.lastUnpackAlignment[0]); + glPixelStorei(GL_UNPACK_ROW_LENGTH, props.lastUnpackRowLength[0]); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, props.lastUnpackSkipPixels[0]); + glPixelStorei(GL_UNPACK_SKIP_ROWS, props.lastUnpackSkipRows[0]); + + if (glVersion >= 120) { + glPixelStorei(GL_PACK_IMAGE_HEIGHT, props.lastPackImageHeight[0]); + glPixelStorei(GL_PACK_SKIP_IMAGES, props.lastPackSkipImages[0]); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, props.lastUnpackImageHeight[0]); + glPixelStorei(GL_UNPACK_SKIP_IMAGES, props.lastUnpackSkipImages[0]); + } + + glDepthMask(props.isLastDepthMask()); + + return this; + } +} diff --git a/src/main/java/cn/pupperclient/skia/gl/States.java b/src/main/java/cn/pupperclient/skia/gl/States.java new file mode 100644 index 0000000..e3b6803 --- /dev/null +++ b/src/main/java/cn/pupperclient/skia/gl/States.java @@ -0,0 +1,71 @@ +/* + * This file is part of https://github.com/Lyzev/Skija. + * + * Copyright (c) 2024-2025. Lyzev + * + * Skija is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3 of the License, or + * (at your option) any later version. + * + * Skija is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Skija. If not, see . + */ + +package cn.pupperclient.skia.gl; + +import org.lwjgl.opengl.GL30.*; +import java.util.Stack; + +import static org.lwjgl.opengl.GL11.glGetIntegerv; +import static org.lwjgl.opengl.GL30C.GL_MAJOR_VERSION; +import static org.lwjgl.opengl.GL30C.GL_MINOR_VERSION; + +/** + * Stores and restores OpenGL states. + */ +public final class States { + + /** + * The current OpenGL version. + */ + private static final int GL_VERSION; + + /** + * The stack of OpenGL states. + */ + private static final Stack STATES = new Stack<>(); + + private States() { + // private constructor to prevent instantiation + } + + /** + * Pushes the current OpenGL state onto the stack. + */ + public static void push() { + STATES.push(new State(GL_VERSION).push()); + } + + /** + * Pops the last OpenGL state from the stack and restores it. + */ + public static void pop() { + if (STATES.isEmpty()) { + throw new IllegalStateException("No state to restore."); + } + STATES.pop().pop(); + } + + static { + int[] major = new int[1]; + int[] minor = new int[1]; + glGetIntegerv(GL_MAJOR_VERSION, major); + glGetIntegerv(GL_MINOR_VERSION, minor); + GL_VERSION = major[0] * 100 + minor[0] * 10; + } +} diff --git a/src/main/java/cn/pupperclient/skia/image/ImageHelper.java b/src/main/java/cn/pupperclient/skia/image/ImageHelper.java index 579fb35..016f6f2 100644 --- a/src/main/java/cn/pupperclient/skia/image/ImageHelper.java +++ b/src/main/java/cn/pupperclient/skia/image/ImageHelper.java @@ -8,7 +8,10 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; - +import net.minecraft.client.Minecraft; +import net.minecraft.resources.Identifier; +import net.minecraft.server.packs.resources.Resource; +import net.minecraft.server.packs.resources.ResourceManager; import org.lwjgl.opengl.GL11; import cn.pupperclient.skia.context.SkiaContext; @@ -17,42 +20,42 @@ import io.github.humbleui.skija.ColorType; import io.github.humbleui.skija.Image; import io.github.humbleui.skija.SurfaceOrigin; -import net.minecraft.client.MinecraftClient; -import net.minecraft.resource.Resource; -import net.minecraft.resource.ResourceManager; -import net.minecraft.util.Identifier; public class ImageHelper { private Map images = new HashMap<>(); - private Map textures = new HashMap<>(); + private Map textures = new HashMap<>(); public boolean load(int texture, float width, float height, SurfaceOrigin origin) { - if (!textures.containsKey(texture)) { - Image image = Image.adoptGLTextureFrom(SkiaContext.getContext(), texture, GL11.GL_TEXTURE_2D, (int) width, - (int) height, GL11.GL_RGBA8, origin, ColorType.RGBA_8888); - textures.put(texture, image); - } + int w = Math.max(1, (int) width); + int h = Math.max(1, (int) height); + TextureEntry existing = textures.get(texture); + if (existing == null || existing.width != w || existing.height != h || existing.origin != origin) { + if (existing != null) { + existing.image.close(); + } + Image image = Image.adoptGLTextureFrom(SkiaContext.getContext(), texture, GL11.GL_TEXTURE_2D, w, h, + GL11.GL_RGBA8, origin, ColorType.RGBA_8888); + textures.put(texture, new TextureEntry(image, w, h, origin)); + } return true; } public boolean load(Identifier identifier) { - if (!images.containsKey(identifier.getPath())) { - ResourceManager resourceManager = MinecraftClient.getInstance().getResourceManager(); + String key = identifier.toString(); + if (!images.containsKey(key)) { + ResourceManager resourceManager = Minecraft.getInstance().getResourceManager(); Resource resource; try { resource = resourceManager.getResourceOrThrow(identifier); - try (InputStream inputStream = resource.getInputStream()) { + try (InputStream inputStream = resource.open()) { byte[] imageData = inputStream.readAllBytes(); Image image = Image.makeDeferredFromEncodedBytes(imageData); - if (image == null) { - return false; - } - images.put(identifier.getPath(), image); + images.put(key, image); return true; } catch (IOException e) { cn.pupperclient.PupperLogger.error("ImageHelper", "Failed to read identifier bytes", e); @@ -60,8 +63,6 @@ public boolean load(Identifier identifier) { } catch (FileNotFoundException e) { cn.pupperclient.PupperLogger.error("ImageHelper", "Identifier resource not found", e); } - - } return true; } @@ -107,8 +108,9 @@ public Image get(String path) { public Image get(int texture) { - if (textures.containsKey(texture)) { - return textures.get(texture); + TextureEntry entry = textures.get(texture); + if (entry != null) { + return entry.image; } return null; @@ -117,7 +119,10 @@ public Image get(int texture) { public void clear() { images.values().forEach(Image::close); images.clear(); - textures.values().forEach(Image::close); + textures.values().forEach(entry -> entry.image.close()); textures.clear(); } + + private record TextureEntry(Image image, int width, int height, SurfaceOrigin origin) { + } } diff --git a/src/main/java/cn/pupperclient/ui/component/Component.java b/src/main/java/cn/pupperclient/ui/component/Component.java index aad3c5b..bd1e862 100644 --- a/src/main/java/cn/pupperclient/ui/component/Component.java +++ b/src/main/java/cn/pupperclient/ui/component/Component.java @@ -1,12 +1,11 @@ package cn.pupperclient.ui.component; import cn.pupperclient.ui.component.handler.ComponentHandler; - -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; public class Component { - protected MinecraftClient client = MinecraftClient.getInstance(); + protected Minecraft client = Minecraft.getInstance(); protected ComponentHandler handler; protected float x, y, width, height; @@ -26,7 +25,7 @@ public void mousePressed(double mouseX, double mouseY, int button) { public void mouseReleased(double mouseX, double mouseY, int button) { } - public void charTyped(char chr, int modifiers) { + public void charTyped(int chr) { } public void keyPressed(int keyCode, int scanCode, int modifiers) { diff --git a/src/main/java/cn/pupperclient/ui/component/handler/impl/KeybindHandler.java b/src/main/java/cn/pupperclient/ui/component/handler/impl/KeybindHandler.java index ff3643c..0997730 100644 --- a/src/main/java/cn/pupperclient/ui/component/handler/impl/KeybindHandler.java +++ b/src/main/java/cn/pupperclient/ui/component/handler/impl/KeybindHandler.java @@ -1,8 +1,7 @@ package cn.pupperclient.ui.component.handler.impl; import cn.pupperclient.ui.component.handler.ComponentHandler; - -import net.minecraft.client.util.InputUtil.Key; +import com.mojang.blaze3d.platform.InputConstants.Key; public abstract class KeybindHandler extends ComponentHandler { public abstract void onBinded(Key key); diff --git a/src/main/java/cn/pupperclient/ui/component/impl/Keybind.java b/src/main/java/cn/pupperclient/ui/component/impl/Keybind.java index 3b27ff9..be19ac5 100644 --- a/src/main/java/cn/pupperclient/ui/component/impl/Keybind.java +++ b/src/main/java/cn/pupperclient/ui/component/impl/Keybind.java @@ -1,5 +1,6 @@ package cn.pupperclient.ui.component.impl; +import net.minecraft.client.input.KeyEvent; import org.lwjgl.glfw.GLFW; import cn.pupperclient.PupperClient; @@ -10,17 +11,16 @@ import cn.pupperclient.ui.component.api.PressAnimation; import cn.pupperclient.ui.component.handler.impl.KeybindHandler; import cn.pupperclient.utils.mouse.MouseUtils; - -import net.minecraft.client.util.InputUtil; +import com.mojang.blaze3d.platform.InputConstants; public class Keybind extends Component { private PressAnimation pressAnimation = new PressAnimation(); private boolean binding; - private InputUtil.Key key; + private InputConstants.Key key; - public Keybind(float x, float y, InputUtil.Key key) { + public Keybind(float x, float y, InputConstants.Key key) { super(x, y); this.key = key; width = 126; @@ -38,7 +38,7 @@ public void draw(double mouseX, double mouseY) { pressAnimation.draw(x, y, width, height, palette.getPrimaryContainer(), 0.12F); Skia.restore(); - Skia.drawFullCenteredText(binding ? "..." : key.getLocalizedText().getString(), x + (width / 2), + Skia.drawFullCenteredText(binding ? "..." : key.getDisplayName().getString(), x + (width / 2), y + (height / 2), palette.getSurface(), Fonts.getMedium(14)); } @@ -62,10 +62,10 @@ public void mouseReleased(double mouseX, double mouseY, int button) { if (binding) { if (button == GLFW.GLFW_MOUSE_BUTTON_MIDDLE) { - setKeyCode(InputUtil.UNKNOWN_KEY); + setKeyCode(InputConstants.UNKNOWN); } else if (button != GLFW.GLFW_MOUSE_BUTTON_LEFT && button != GLFW.GLFW_MOUSE_BUTTON_RIGHT && button != GLFW.GLFW_MOUSE_BUTTON_MIDDLE) { - setKeyCode(InputUtil.Type.MOUSE.createFromCode(button)); + setKeyCode(InputConstants.Type.MOUSE.getOrCreate(button)); } binding = false; @@ -77,16 +77,16 @@ public void mouseReleased(double mouseX, double mouseY, int button) { @Override public void keyPressed(int keyCode, int scanCode, int modifiers) { if (binding) { - setKeyCode(InputUtil.fromKeyCode(keyCode, scanCode)); + setKeyCode(InputConstants.getKey(new KeyEvent(keyCode, scanCode, modifiers))); this.binding = false; } } - public InputUtil.Key getKeyCode() { + public InputConstants.Key getKeyCode() { return key; } - public void setKeyCode(InputUtil.Key key) { + public void setKeyCode(InputConstants.Key key) { this.key = key; diff --git a/src/main/java/cn/pupperclient/ui/component/impl/text/SearchBar.java b/src/main/java/cn/pupperclient/ui/component/impl/text/SearchBar.java index 1656c05..bbad9cb 100644 --- a/src/main/java/cn/pupperclient/ui/component/impl/text/SearchBar.java +++ b/src/main/java/cn/pupperclient/ui/component/impl/text/SearchBar.java @@ -172,8 +172,8 @@ public void keyPressed(int keyCode, int scanCode, int modifiers) { } @Override - public void charTyped(char chr, int modifiers) { - input.charTyped(chr, modifiers); + public void charTyped(int chr) { + input.charTyped(chr); } public String getHintText() { diff --git a/src/main/java/cn/pupperclient/ui/component/impl/text/TextField.java b/src/main/java/cn/pupperclient/ui/component/impl/text/TextField.java index 9cb09e0..21983cb 100644 --- a/src/main/java/cn/pupperclient/ui/component/impl/text/TextField.java +++ b/src/main/java/cn/pupperclient/ui/component/impl/text/TextField.java @@ -135,9 +135,9 @@ public void keyPressed(int keyCode, int scanCode, int modifiers) { } @Override - public void charTyped(char chr, int modifiers) { + public void charTyped(int chr) { - input.charTyped(chr, modifiers); + input.charTyped(chr); if (handler instanceof TextHandler) { ((TextHandler) handler).onTyped(getText()); diff --git a/src/main/java/cn/pupperclient/ui/component/impl/text/TextInputHelper.java b/src/main/java/cn/pupperclient/ui/component/impl/text/TextInputHelper.java index 411ecde..b986edf 100644 --- a/src/main/java/cn/pupperclient/ui/component/impl/text/TextInputHelper.java +++ b/src/main/java/cn/pupperclient/ui/component/impl/text/TextInputHelper.java @@ -3,13 +3,12 @@ import org.lwjgl.glfw.GLFW; import cn.pupperclient.utils.math.MathUtils; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.StringHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.util.StringUtil; public class TextInputHelper { - private MinecraftClient client = MinecraftClient.getInstance(); + private Minecraft client = Minecraft.getInstance(); private String text; private boolean focused; @@ -28,13 +27,13 @@ public void keyPressed(int keyCode, int scanCode, int modifiers) { if (!focused) { return; } else if (modifiers == GLFW.GLFW_MOD_CONTROL && keyCode == GLFW.GLFW_KEY_C) { - client.keyboard.setClipboard(this.getSelectedText()); + client.keyboardHandler.setClipboard(this.getSelectedText()); return; } else if (modifiers == GLFW.GLFW_MOD_CONTROL && keyCode == GLFW.GLFW_KEY_V) { - writeText(client.keyboard.getClipboard()); + writeText(client.keyboardHandler.getClipboard()); return; } else if (modifiers == GLFW.GLFW_MOD_CONTROL && keyCode == GLFW.GLFW_KEY_X) { - client.keyboard.setClipboard(this.getSelectedText()); + client.keyboardHandler.setClipboard(this.getSelectedText()); this.writeText(""); return; } else if (modifiers == GLFW.GLFW_MOD_CONTROL && keyCode == GLFW.GLFW_KEY_A) { @@ -103,8 +102,8 @@ public void keyPressed(int keyCode, int scanCode, int modifiers) { } } - public void charTyped(char chr, int modifiers) { - if (StringHelper.isValidChar(chr) && this.isFocused()) { + public void charTyped(int chr) { + if (StringUtil.isAllowedChatCharacter(chr) && this.isFocused()) { this.writeText(Character.toString(chr)); } } @@ -112,7 +111,7 @@ public void charTyped(char chr, int modifiers) { private void writeText(String text) { String s = ""; - String s1 = StringHelper.stripInvalidChars(text); + String s1 = StringUtil.filterText(text); int min = Math.min(this.cursorPosition, this.selectionEnd); int max = Math.max(this.cursorPosition, this.selectionEnd); int len = this.maxStringLength - this.text.length() - (min - max); diff --git a/src/main/java/cn/pupperclient/utils/chat/ChatUtils.java b/src/main/java/cn/pupperclient/utils/chat/ChatUtils.java index c55ac1a..ffd311c 100644 --- a/src/main/java/cn/pupperclient/utils/chat/ChatUtils.java +++ b/src/main/java/cn/pupperclient/utils/chat/ChatUtils.java @@ -1,29 +1,27 @@ package cn.pupperclient.utils.chat; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.ChatComponent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; public class ChatUtils { private static final String PREFIX = "§7[§bPupper§7] "; - private static final String PREFIX_FORMATTED = Formatting.GRAY + "[" + Formatting.AQUA + "Pupper" + Formatting.GRAY + "] "; - private static final Text PREFIX_TEXT = Text.literal("[") - .formatted(Formatting.GRAY) - .append(Text.literal("PupperClient").formatted(Formatting.AQUA)) - .append(Text.literal("] ").formatted(Formatting.GRAY)); + private static final String PREFIX_FORMATTED = ChatFormatting.GRAY + "[" + ChatFormatting.AQUA + "Pupper" + ChatFormatting.GRAY + "] "; + private static final Component PREFIX_TEXT = Component.literal("[") + .withStyle(ChatFormatting.GRAY) + .append(Component.literal("PupperClient").withStyle(ChatFormatting.AQUA)) + .append(Component.literal("] ").withStyle(ChatFormatting.GRAY)); - public static void component(Text component) { - MinecraftClient client = MinecraftClient.getInstance(); - if (client == null || client.world == null) return; + public static void component(Component component) { + Minecraft client = Minecraft.getInstance(); + if (client.level == null) return; client.execute(() -> { - ChatHud chat = client.inGameHud.getChatHud(); - if (chat != null) { - chat.addMessage(component); - } + ChatComponent chat = client.gui.getChat(); + chat.addClientSystemMessage(component); }); } @@ -31,10 +29,10 @@ public static void addChatMessage(String message) { addChatMessage(true, message); } - public static void addChatMessage(Text message) { + public static void addChatMessage(Component message) { if (message == null || message.getString().isEmpty()) return; - MutableText fullMessage = Text.empty() + MutableComponent fullMessage = Component.empty() .append(PREFIX_TEXT) .append(message); @@ -45,29 +43,36 @@ public static void addChatMessage(boolean prefix, String message) { if (message == null || message.isEmpty()) return; String formattedMessage = (prefix ? PREFIX : "") + message; - component(Text.literal(formattedMessage)); + component(Component.literal(formattedMessage)); } - public static void addFormattedMessage(String message, Formatting... formattings) { - MutableText text = Text.literal(PREFIX_FORMATTED).formatted(Formatting.GRAY); - text.append(Text.literal(message).formatted(formattings)); + public static void addChatMessage(boolean prefix, Component message) { + if (message == null) return; + + String formattedMessage = (prefix ? PREFIX : "") + message.getString(); + component(Component.literal(formattedMessage)); + } + + public static void addFormattedMessage(String message, ChatFormatting... formattings) { + MutableComponent text = Component.literal(PREFIX_FORMATTED).withStyle(ChatFormatting.GRAY); + text.append(Component.literal(message).withStyle(formattings)); component(text); } public static void error(String message) { - addFormattedMessage(message, Formatting.RED); + addFormattedMessage(message, ChatFormatting.RED); } public static void success(String message) { - addFormattedMessage(message, Formatting.GREEN); + addFormattedMessage(message, ChatFormatting.GREEN); } public static void warning(String message) { - addFormattedMessage(message, Formatting.YELLOW); + addFormattedMessage(message, ChatFormatting.YELLOW); } public static void info(String message) { - addFormattedMessage(message, Formatting.BLUE); + addFormattedMessage(message, ChatFormatting.BLUE); } } diff --git a/src/main/java/cn/pupperclient/utils/color/Color.java b/src/main/java/cn/pupperclient/utils/color/Color.java new file mode 100644 index 0000000..4748339 --- /dev/null +++ b/src/main/java/cn/pupperclient/utils/color/Color.java @@ -0,0 +1,365 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package cn.pupperclient.utils.color; + +import cn.pupperclient.utils.misc.ICopyable; +import cn.pupperclient.utils.misc.ISerializable; +import net.minecraft.ChatFormatting; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Style; +import net.minecraft.network.chat.TextColor; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.joml.Vector3f; +import org.joml.Vector4f; + +@SuppressWarnings("unused") +public class Color implements ICopyable, ISerializable { + public static final Color CLEAR = new Color(0, 0, 0, 0); + public static final Color WHITE = new Color(java.awt.Color.WHITE); + public static final Color LIGHT_GRAY = new Color(java.awt.Color.LIGHT_GRAY); + public static final Color GRAY = new Color(java.awt.Color.GRAY); + public static final Color DARK_GRAY = new Color(java.awt.Color.DARK_GRAY); + public static final Color BLACK = new Color(java.awt.Color.BLACK); + public static final Color RED = new Color(java.awt.Color.RED); + public static final Color PINK = new Color(java.awt.Color.PINK); + public static final Color ORANGE = new Color(java.awt.Color.ORANGE); + public static final Color YELLOW = new Color(java.awt.Color.YELLOW); + public static final Color GREEN = new Color(java.awt.Color.GREEN); + public static final Color MAGENTA = new Color(java.awt.Color.MAGENTA); + public static final Color CYAN = new Color(java.awt.Color.CYAN); + public static final Color BLUE = new Color(java.awt.Color.BLUE); + + public int r, g, b, a; + + public Color() { + this(255, 255, 255, 255); + } + + public Color(int r, int g, int b) { + this.r = r; + this.g = g; + this.b = b; + this.a = 255; + + validate(); + } + + public Color(int r, int g, int b, int a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + + validate(); + } + + public Color(float r, float g, float b, float a) { + this.r = (int)(r*255); + this.g = (int)(g*255); + this.b = (int)(b*255); + this.a = (int)(a*255); + + validate(); + } + + public Color(int packed) { + this.r = toRGBAR(packed); + this.g = toRGBAG(packed); + this.b = toRGBAB(packed); + this.a = toRGBAA(packed); + } + + public Color(Color color) { + this.r = color.r; + this.g = color.g; + this.b = color.b; + this.a = color.a; + } + + public Color(java.awt.Color color) { + this.r = color.getRed(); + this.g = color.getGreen(); + this.b = color.getBlue(); + this.a = color.getAlpha(); + } + + public Color(@NotNull ChatFormatting formatting) { + if (formatting.isColor()) { + this.r = toRGBAR(formatting.getColor()); + this.g = toRGBAG(formatting.getColor()); + this.b = toRGBAB(formatting.getColor()); + this.a = toRGBAA(formatting.getColor()); + } else { + this.r = 255; + this.g = 255; + this.b = 255; + this.a = 255; + } + } + + public Color(TextColor textColor) { + this.r = toRGBAR(textColor.getValue()); + this.g = toRGBAG(textColor.getValue()); + this.b = toRGBAB(textColor.getValue()); + this.a = toRGBAA(textColor.getValue()); + } + + public Color(Style style) { + TextColor textColor = style.getColor(); + if (textColor == null) { + this.r = 255; + this.g = 255; + this.b = 255; + this.a = 255; + } else { + this.r = toRGBAR(textColor.getValue()); + this.g = toRGBAG(textColor.getValue()); + this.b = toRGBAB(textColor.getValue()); + this.a = toRGBAA(textColor.getValue()); + } + } + + public static int fromRGBA(int r, int g, int b, int a) { + return (r << 16) + (g << 8) + (b) + (a << 24); + } + + public static int toRGBAR(int color) { + return (color >> 16) & 0x000000FF; + } + + public static int toRGBAG(int color) { + return (color >> 8) & 0x000000FF; + } + + public static int toRGBAB(int color) { + return (color) & 0x000000FF; + } + + public static int toRGBAA(int color) { + return (color >> 24) & 0x000000FF; + } + + public static Color fromHsv(double h, double s, double v) { + double hh, p, q, t, ff; + int i; + double r, g, b; + + if (s <= 0.0) { // < is bogus, just shuts up warnings + r = v; + g = v; + b = v; + return new Color((int) (r * 255), (int) (g * 255), (int) (b * 255), 255); + } + hh = h; + if (hh >= 360.0) hh = 0.0; + hh /= 60.0; + i = (int) hh; + ff = hh - i; + p = v * (1.0 - s); + q = v * (1.0 - (s * ff)); + t = v * (1.0 - (s * (1.0 - ff))); + + switch (i) { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + case 5: + default: + r = v; + g = p; + b = q; + break; + } + return new Color((int) (r * 255), (int) (g * 255), (int) (b * 255), 255); + } + + public Color set(int r, int g, int b, int a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + + validate(); + + return this; + } + + public Color r(int r) { + this.r = r; + validate(); + return this; + } + + public Color g(int g) { + this.g = g; + validate(); + return this; + } + + public Color b(int b) { + this.b = b; + validate(); + return this; + } + + public Color a(int a) { + this.a = a; + validate(); + return this; + } + + @Override + public Color set(Color value) { + r = value.r; + g = value.g; + b = value.b; + a = value.a; + + validate(); + + return this; + } + + public boolean parse(String text) { + String[] split = text.split(","); + if (split.length != 3 && split.length != 4) return false; + + try { + // Not assigned directly because of exception handling + int r = Integer.parseInt(split[0]); + int g = Integer.parseInt(split[1]); + int b = Integer.parseInt(split[2]); + int a = split.length == 4 ? Integer.parseInt(split[3]) : this.a; + + this.r = r; + this.g = g; + this.b = b; + this.a = a; + + return true; + } catch (NumberFormatException ignored) { + return false; + } + } + + @Override + public Color copy() { + return new Color(r, g, b, a); + } + + public TextColor toTextColor() { + return TextColor.fromRgb(getPacked()); + } + + public Style toStyle() { + return Style.EMPTY.withColor(toTextColor()); + } + + public Style styleWith(Style style) { + return style.withColor(toTextColor()); + } + + public void validate() { + if (r < 0) r = 0; + else if (r > 255) r = 255; + + if (g < 0) g = 0; + else if (g > 255) g = 255; + + if (b < 0) b = 0; + else if (b > 255) b = 255; + + if (a < 0) a = 0; + else if (a > 255) a = 255; + } + + public Vec3 getVec3() { + return new Vec3(r / 255.0, g / 255.0, b / 255.0); + } + + public Vector3f getVec3f() { + return new Vector3f(r / 255.0f, g / 255.0f, b / 255.0f); + } + + public Vector4f getVec4f() { + return new Vector4f(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); + } + + public int getPacked() { + return fromRGBA(r, g, b, a); + } + + @Override + public CompoundTag toTag() { + CompoundTag tag = new CompoundTag(); + + tag.putInt("r", r); + tag.putInt("g", g); + tag.putInt("b", b); + tag.putInt("a", a); + + return tag; + } + + @Override + public Color fromTag(CompoundTag tag) { + r = tag.getInt("r").orElse(0); + g = tag.getInt("g").orElse(0); + b = tag.getInt("b").orElse(0); + a = tag.getInt("a").orElse(0); + + validate(); + return this; + } + + @Override + public String toString() { + return r + " " + g + " " + b + " " + a; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Color color = (Color) o; + + return r == color.r && g == color.g && b == color.b && a == color.a; + } + + @Override + public int hashCode() { + int result = r; + result = 31 * result + g; + result = 31 * result + b; + result = 31 * result + a; + return result; + } +} diff --git a/src/main/java/cn/pupperclient/utils/file/FileLocation.java b/src/main/java/cn/pupperclient/utils/file/FileLocation.java index d88b65e..8241303 100644 --- a/src/main/java/cn/pupperclient/utils/file/FileLocation.java +++ b/src/main/java/cn/pupperclient/utils/file/FileLocation.java @@ -1,12 +1,11 @@ package cn.pupperclient.utils.file; import java.io.File; - -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; public class FileLocation { - public static final File MAIN_DIR = new File(MinecraftClient.getInstance().runDirectory, "pupper"); + public static final File MAIN_DIR = new File(Minecraft.getInstance().gameDirectory, "pupper"); public static final File MUSIC_DIR = new File(MAIN_DIR, "music"); public static final File CACHE_DIR = new File(MAIN_DIR, "cache"); public static final File CONFIG_DIR = new File(MAIN_DIR, "config"); diff --git a/src/main/java/cn/pupperclient/utils/file/FileUtils.java b/src/main/java/cn/pupperclient/utils/file/FileUtils.java index 85116f6..9dd0c4e 100644 --- a/src/main/java/cn/pupperclient/utils/file/FileUtils.java +++ b/src/main/java/cn/pupperclient/utils/file/FileUtils.java @@ -1,5 +1,7 @@ package cn.pupperclient.utils.file; +import org.jspecify.annotations.NonNull; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -20,19 +22,19 @@ public class FileUtils { public static void deleteDirectory(Path directory) throws IOException { if (!Files.exists(directory)) return; - Files.walkFileTree(directory, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } + Files.walkFileTree(directory, new SimpleFileVisitor<>() { + @Override + public @NonNull FileVisitResult visitFile(@NonNull Path file, @NonNull BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - }); + @Override + public @NonNull FileVisitResult postVisitDirectory(@NonNull Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); } public static void zip(File source, File zipFile) throws IOException { diff --git a/src/main/java/cn/pupperclient/utils/minecraft/interfaces/IMinecraft.java b/src/main/java/cn/pupperclient/utils/minecraft/interfaces/IMinecraft.java index c61e00c..b3b65e1 100644 --- a/src/main/java/cn/pupperclient/utils/minecraft/interfaces/IMinecraft.java +++ b/src/main/java/cn/pupperclient/utils/minecraft/interfaces/IMinecraft.java @@ -1,7 +1,7 @@ package cn.pupperclient.utils.minecraft.interfaces; -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; public interface IMinecraft { - MinecraftClient mc = MinecraftClient.getInstance(); + Minecraft client = Minecraft.getInstance(); } diff --git a/src/main/java/cn/pupperclient/utils/minecraft/player/HealthUtils.java b/src/main/java/cn/pupperclient/utils/minecraft/player/HealthUtils.java index 9bff7ce..a9be379 100644 --- a/src/main/java/cn/pupperclient/utils/minecraft/player/HealthUtils.java +++ b/src/main/java/cn/pupperclient/utils/minecraft/player/HealthUtils.java @@ -1,10 +1,10 @@ package cn.pupperclient.utils.minecraft.player; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.LivingEntity; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.scoreboard.ScoreboardDisplaySlot; -import net.minecraft.scoreboard.ScoreboardObjective; +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.scores.DisplaySlot; +import net.minecraft.world.scores.Objective; +import net.minecraft.world.scores.Scoreboard; public class HealthUtils { private static final String[] HP_KEYWORDS = {"hp", "health", "♥", "lives"}; @@ -24,25 +24,25 @@ public static float getActualHealth(LivingEntity entity) { } private static Float getHealthFromScoreboard(LivingEntity entity) { - MinecraftClient client = MinecraftClient.getInstance(); - if (client.world == null) return null; + Minecraft client = Minecraft.getInstance(); + if (client.level == null) return null; - Scoreboard scoreboard = client.world.getScoreboard(); - ScoreboardObjective objective = scoreboard.getObjectiveForSlot(ScoreboardDisplaySlot.BELOW_NAME); + Scoreboard scoreboard = client.level.getScoreboard(); + Objective objective = scoreboard.getDisplayObjective(DisplaySlot.BELOW_NAME); if (objective == null) return null; try { - var score = objective.getScoreboard().getScore(entity, objective); + var score = objective.getScoreboard().getPlayerScoreInfo(entity, objective); if (score == null) return null; var displayName = objective.getDisplayName(); - if (score.getScore() <= 0 || displayName == null || !containsHealthKeyword(displayName.getString())) { + if (score.value() <= 0 || displayName == null || !containsHealthKeyword(displayName.getString())) { return null; } - return (float) score.getScore(); + return (float) score.value(); } catch (Exception e) { return null; } diff --git a/src/main/java/cn/pupperclient/utils/minecraft/player/SkinUtils.java b/src/main/java/cn/pupperclient/utils/minecraft/player/SkinUtils.java index 15e43d9..ae2b4f5 100644 --- a/src/main/java/cn/pupperclient/utils/minecraft/player/SkinUtils.java +++ b/src/main/java/cn/pupperclient/utils/minecraft/player/SkinUtils.java @@ -1,18 +1,16 @@ package cn.pupperclient.utils.minecraft.player; import java.io.File; - +import net.minecraft.client.Minecraft; +import net.minecraft.resources.Identifier; import cn.pupperclient.mixin.interfaces.IMixinMinecraftClient; -import net.minecraft.client.MinecraftClient; -import net.minecraft.util.Identifier; - public class SkinUtils { public static File getSkin(Identifier identifier) { String fileName = identifier.getPath().replace("skins/", ""); String folder = fileName.substring(0, 2); - File file = new File(((IMixinMinecraftClient) MinecraftClient.getInstance()).getAssetDir(), + File file = new File(((IMixinMinecraftClient) Minecraft.getInstance()).pupper$getAssetDir(), "skins/" + folder + "/" + fileName); return file; } diff --git a/src/main/java/cn/pupperclient/utils/misc/ICopyable.java b/src/main/java/cn/pupperclient/utils/misc/ICopyable.java new file mode 100644 index 0000000..1cc5d03 --- /dev/null +++ b/src/main/java/cn/pupperclient/utils/misc/ICopyable.java @@ -0,0 +1,12 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package cn.pupperclient.utils.misc; + +public interface ICopyable> { + T set(T value); + + T copy(); +} diff --git a/src/main/java/cn/pupperclient/utils/misc/ISerializable.java b/src/main/java/cn/pupperclient/utils/misc/ISerializable.java new file mode 100644 index 0000000..f3fc79c --- /dev/null +++ b/src/main/java/cn/pupperclient/utils/misc/ISerializable.java @@ -0,0 +1,13 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.utils.misc; + +import net.minecraft.nbt.CompoundTag; + +public interface ISerializable { + CompoundTag toTag(); + + T fromTag(CompoundTag tag); +} diff --git a/src/main/java/cn/pupperclient/utils/misc/SoundEventHelper.java b/src/main/java/cn/pupperclient/utils/misc/SoundEventHelper.java index c59eb3d..0ab1538 100644 --- a/src/main/java/cn/pupperclient/utils/misc/SoundEventHelper.java +++ b/src/main/java/cn/pupperclient/utils/misc/SoundEventHelper.java @@ -1,7 +1,7 @@ package cn.pupperclient.utils.misc; -import net.minecraft.entity.Entity; -import net.minecraft.sound.SoundEvent; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.entity.Entity; public class SoundEventHelper { public static Entity lastSoundSource; diff --git a/src/main/java/cn/pupperclient/utils/render/PupperGuiRenderer.java b/src/main/java/cn/pupperclient/utils/render/PupperGuiRenderer.java new file mode 100644 index 0000000..feb32c9 --- /dev/null +++ b/src/main/java/cn/pupperclient/utils/render/PupperGuiRenderer.java @@ -0,0 +1,20 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.utils.render; + +import net.minecraft.client.gui.render.GuiRenderer; +import net.minecraft.client.gui.render.pip.PictureInPictureRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.feature.FeatureRenderDispatcher; +import net.minecraft.client.renderer.state.gui.GuiRenderState; + +import java.util.List; + +public class PupperGuiRenderer extends GuiRenderer { + public PupperGuiRenderer(GuiRenderState renderState, MultiBufferSource.BufferSource bufferSource, SubmitNodeCollector submitNodeCollector, FeatureRenderDispatcher featureRenderDispatcher, List> pictureInPictureRenderers) { + super(renderState, bufferSource, submitNodeCollector, featureRenderDispatcher, pictureInPictureRenderers); + } +} diff --git a/src/main/java/cn/pupperclient/utils/render/RenderUtils.java b/src/main/java/cn/pupperclient/utils/render/RenderUtils.java new file mode 100644 index 0000000..fbfa0a7 --- /dev/null +++ b/src/main/java/cn/pupperclient/utils/render/RenderUtils.java @@ -0,0 +1,45 @@ +/** + * @Author: oneachina + * @link: github.com/oneachina + */ +package cn.pupperclient.utils.render; + +import cn.pupperclient.utils.minecraft.interfaces.IMinecraft; +import com.mojang.blaze3d.ProjectionType; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.renderer.Projection; +import net.minecraft.client.renderer.ProjectionMatrixBuffer; +import org.joml.Matrix4f; + +public class RenderUtils implements IMinecraft { + public static final Matrix4f projection = new Matrix4f(); + private static final ProjectionMatrixBuffer matrixBuffer = new ProjectionMatrixBuffer("pupper-projection-matrix"); + + public static void unscaledProjection() { + float width = client.getWindow().getWidth(); + float height = client.getWindow().getHeight(); + + var proj = new Projection(); + proj.setupOrtho(-10, 100, width, height, true); + var matrix = proj.getMatrix(new Matrix4f()); + + RenderSystem.setProjectionMatrix(matrixBuffer.getBuffer(matrix), ProjectionType.ORTHOGRAPHIC); + RenderUtils.projection.set(matrix); + } + + public static void scaledProjection() { + float width = (float) (client.getWindow().getWidth() / client.getWindow().getGuiScale()); + float height = (float) (client.getWindow().getHeight() / client.getWindow().getGuiScale()); + + var proj = new Projection(); + proj.setupOrtho(-10, 100, width, height, true); + var matrix = proj.getMatrix(new Matrix4f()); + + RenderSystem.setProjectionMatrix(matrixBuffer.getBuffer(matrix), ProjectionType.PERSPECTIVE); + RenderUtils.projection.set(matrix); + } + + public static boolean canUpdate() { + return client.level != null && client.player != null; + } +} diff --git a/src/main/java/cn/pupperclient/utils/server/ServerUtils.java b/src/main/java/cn/pupperclient/utils/server/ServerUtils.java index 0c2c8fe..b885ef2 100644 --- a/src/main/java/cn/pupperclient/utils/server/ServerUtils.java +++ b/src/main/java/cn/pupperclient/utils/server/ServerUtils.java @@ -1,26 +1,25 @@ package cn.pupperclient.utils.server; -import net.minecraft.client.MinecraftClient; - import java.util.Objects; +import net.minecraft.client.Minecraft; public class ServerUtils { - private static final MinecraftClient client = MinecraftClient.getInstance(); + private static final Minecraft client = Minecraft.getInstance(); public static boolean isJoin(Server server) { return isMultiplayer() && getAddress().contains(server.getAddress()); } public static boolean isSingleplayer() { - return client.isConnectedToLocalServer(); + return client.isSingleplayer(); } public static boolean isMultiplayer() { - return client.getCurrentServerEntry() != null; + return client.getCurrentServer() != null; } public static String getAddress() { - return isMultiplayer() ? Objects.requireNonNull(client.getCurrentServerEntry()).address : "null"; + return isMultiplayer() ? Objects.requireNonNull(client.getCurrentServer()).ip : "null"; } } diff --git a/src/main/java/cn/pupperclient/utils/thread/Multithreading.java b/src/main/java/cn/pupperclient/utils/thread/Multithreading.java index 3661ba3..b2de3c7 100644 --- a/src/main/java/cn/pupperclient/utils/thread/Multithreading.java +++ b/src/main/java/cn/pupperclient/utils/thread/Multithreading.java @@ -1,9 +1,8 @@ package cn.pupperclient.utils.thread; import java.util.concurrent.*; - +import net.minecraft.client.Minecraft; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import net.minecraft.client.MinecraftClient; public class Multithreading { private static final ExecutorService virtualThreadExecutor = Executors.newVirtualThreadPerTaskExecutor(); @@ -25,7 +24,7 @@ public static void runAsync(Runnable runnable) { } public static void runMainThread(Runnable runnable) { - MinecraftClient.getInstance().execute(runnable); + Minecraft.getInstance().execute(runnable); } public static void submit(Runnable runnable) { diff --git a/src/main/resources/assets/pupper/natives/smtc.dll b/src/main/resources/assets/pupper/natives/smtc.dll deleted file mode 100644 index e5bcc2c..0000000 Binary files a/src/main/resources/assets/pupper/natives/smtc.dll and /dev/null differ diff --git a/src/main/resources/assets/pupper/oldlogo.png b/src/main/resources/assets/pupper/oldlogo.png deleted file mode 100644 index c893264..0000000 Binary files a/src/main/resources/assets/pupper/oldlogo.png and /dev/null differ diff --git a/src/main/resources/assets/pupper/shaders/blur.vert b/src/main/resources/assets/pupper/shaders/blur.vsh similarity index 100% rename from src/main/resources/assets/pupper/shaders/blur.vert rename to src/main/resources/assets/pupper/shaders/blur.vsh diff --git a/src/main/resources/assets/pupper/shaders/blur_down.frag b/src/main/resources/assets/pupper/shaders/blur_down.frag deleted file mode 100644 index 7f49298..0000000 --- a/src/main/resources/assets/pupper/shaders/blur_down.frag +++ /dev/null @@ -1,27 +0,0 @@ -#version 330 core - -precision lowp float; - -in vec2 uv; -out vec4 color; - -uniform sampler2D uTexture; -uniform vec2 uHalfTexelSize; -uniform float uOffset; - -vec4 safeTexture2D(sampler2D tex, vec2 uv) { - uv = clamp(uv, 0.001, 0.999); // 防止在边缘采样 - return texture(tex, uv); -} - -void main() { - color = ( - texture(uTexture, uv) * 4 + - texture(uTexture, uv - uHalfTexelSize.xy * uOffset) + - texture(uTexture, uv + uHalfTexelSize.xy * uOffset) + - texture(uTexture, uv + vec2(uHalfTexelSize.x, -uHalfTexelSize.y) * uOffset) + - texture(uTexture, uv - vec2(uHalfTexelSize.x, -uHalfTexelSize.y) * uOffset) - ) / 8; - color.a = 1; -} - diff --git a/src/main/resources/assets/pupper/shaders/blur_down.fsh b/src/main/resources/assets/pupper/shaders/blur_down.fsh new file mode 100644 index 0000000..1b1fcbe --- /dev/null +++ b/src/main/resources/assets/pupper/shaders/blur_down.fsh @@ -0,0 +1,24 @@ +#version 330 core + +precision lowp float; + +in vec2 uv; +out vec4 color; + +uniform sampler2D u_Texture; + +layout (std140) uniform BlurData { + vec2 u_HalfTexelSize; + float u_Offset; +}; + +void main() { + color = ( + texture(u_Texture, uv) * 4 + + texture(u_Texture, uv - u_HalfTexelSize * u_Offset) + + texture(u_Texture, uv + u_HalfTexelSize * u_Offset) + + texture(u_Texture, uv + vec2(u_HalfTexelSize.x, -u_HalfTexelSize.y) * u_Offset) + + texture(u_Texture, uv - vec2(u_HalfTexelSize.x, -u_HalfTexelSize.y) * u_Offset) + ) / 8; + color.a = 1; +} diff --git a/src/main/resources/assets/pupper/shaders/blur_up.frag b/src/main/resources/assets/pupper/shaders/blur_up.frag deleted file mode 100644 index dfd8931..0000000 --- a/src/main/resources/assets/pupper/shaders/blur_up.frag +++ /dev/null @@ -1,30 +0,0 @@ -#version 330 core - -precision lowp float; - -in vec2 uv; -out vec4 color; - -uniform sampler2D uTexture; -uniform vec2 uHalfTexelSize; -uniform float uOffset; - -vec4 safeTexture2D(sampler2D tex, vec2 uv) { - uv = clamp(uv, 0.001, 0.999); // 防止在边缘采样 - return texture(tex, uv); -} - -void main() { - color = ( - texture(uTexture, uv + vec2(- uHalfTexelSize.x * 2, 0) * uOffset) + - texture(uTexture, uv + vec2(- uHalfTexelSize.x, uHalfTexelSize.y) * uOffset) * 2 + - texture(uTexture, uv + vec2(0, uHalfTexelSize.y * 2) * uOffset) + - texture(uTexture, uv + uHalfTexelSize * uOffset) * 2 + - texture(uTexture, uv + vec2(uHalfTexelSize.x * 2, 0) * uOffset) + - texture(uTexture, uv + vec2(uHalfTexelSize.x, -uHalfTexelSize.y) * uOffset) * 2 + - texture(uTexture, uv + vec2(0, -uHalfTexelSize.y * 2) * uOffset) + - texture(uTexture, uv - uHalfTexelSize * uOffset) * 2 - ) / 12; - color.a = 1; -} - diff --git a/src/main/resources/assets/pupper/shaders/blur_up.fsh b/src/main/resources/assets/pupper/shaders/blur_up.fsh new file mode 100644 index 0000000..45a133c --- /dev/null +++ b/src/main/resources/assets/pupper/shaders/blur_up.fsh @@ -0,0 +1,27 @@ +#version 330 core + +precision lowp float; + +in vec2 uv; +out vec4 color; + +uniform sampler2D u_Texture; + +layout (std140) uniform BlurData { + vec2 u_HalfTexelSize; + float u_Offset; +}; + +void main() { + color = ( + texture(u_Texture, uv + vec2(- u_HalfTexelSize.x * 2, 0) * u_Offset) + + texture(u_Texture, uv + vec2(- u_HalfTexelSize.x, u_HalfTexelSize.y) * u_Offset) * 2 + + texture(u_Texture, uv + vec2(0, u_HalfTexelSize.y * 2) * u_Offset) + + texture(u_Texture, uv + u_HalfTexelSize * u_Offset) * 2 + + texture(u_Texture, uv + vec2(u_HalfTexelSize.x * 2, 0) * u_Offset) + + texture(u_Texture, uv + vec2(u_HalfTexelSize.x, -u_HalfTexelSize.y) * u_Offset) * 2 + + texture(u_Texture, uv + vec2(0, -u_HalfTexelSize.y * 2) * u_Offset) + + texture(u_Texture, uv - u_HalfTexelSize * u_Offset) * 2 + ) / 12; + color.a = 1; +} diff --git a/src/main/resources/assets/pupper/shaders/passthrough.frag b/src/main/resources/assets/pupper/shaders/passthrough.fsh similarity index 57% rename from src/main/resources/assets/pupper/shaders/passthrough.frag rename to src/main/resources/assets/pupper/shaders/passthrough.fsh index 6d9dedf..f3483ed 100644 --- a/src/main/resources/assets/pupper/shaders/passthrough.frag +++ b/src/main/resources/assets/pupper/shaders/passthrough.fsh @@ -5,8 +5,8 @@ precision lowp float; in vec2 uv; out vec4 color; -uniform sampler2D uTexture; +uniform sampler2D u_Texture; void main() { - color = texture(uTexture, uv); + color = texture(u_Texture, uv); } diff --git a/src/main/resources/assets/pupper/shaders/passthrough.vert b/src/main/resources/assets/pupper/shaders/passthrough.vsh similarity index 100% rename from src/main/resources/assets/pupper/shaders/passthrough.vert rename to src/main/resources/assets/pupper/shaders/passthrough.vsh diff --git a/src/main/resources/assets/pupper/shaders/pos_color.fsh b/src/main/resources/assets/pupper/shaders/pos_color.fsh new file mode 100644 index 0000000..567156e --- /dev/null +++ b/src/main/resources/assets/pupper/shaders/pos_color.fsh @@ -0,0 +1,9 @@ +#version 330 core + +out vec4 color; + +in vec4 v_Color; + +void main() { + color = v_Color; +} diff --git a/src/main/resources/assets/pupper/shaders/pos_color.vsh b/src/main/resources/assets/pupper/shaders/pos_color.vsh new file mode 100644 index 0000000..352f6ee --- /dev/null +++ b/src/main/resources/assets/pupper/shaders/pos_color.vsh @@ -0,0 +1,17 @@ +#version 330 core + +layout (location = 0) in vec4 pos; +layout (location = 1) in vec4 color; + +layout (std140) uniform MeshData { + mat4 u_Proj; + mat4 u_ModelView; +}; + +out vec4 v_Color; + +void main() { + gl_Position = u_Proj * u_ModelView * pos; + + v_Color = color; +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index fce97ca..a28cd31 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "id": "pupper", "version": "${version}", - "accessWidener": "pupper.accesswidener", + "accessWidener": "pupper.classtweaker", "name": "PupperClient", "icon": "assets/pupper/logo.png", "description": "Better, Faster Minecraft Client", @@ -19,12 +19,23 @@ "pupper.mixins.json" ], "depends": { - "fabricloader": ">=0.16.10", - "fabric": "*", - "minecraft": "1.21.4", - "viafabricplus": "*", - "ias": "*" + "fabricloader": ">=0.18.6", + "fabric-api": ">=0.145.4+26.1.2", + "minecraft": [ + "26.1", + "26.1.1", + "${minecraft_version}" + ], + "viafabricplus": "*" }, + "breaks": { + "optifabric": "*", + "feather": "*", + "origins": "*", + "sodium": "<0.8.7", + "morechathistory": "*", + "lithium": "<0.21.3" + }, "custom": { "pupper:icon": "assets/pupper/logo.png", "modmenu": { diff --git a/src/main/resources/pupper.accesswidener b/src/main/resources/pupper.accesswidener deleted file mode 100644 index 8d73f3a..0000000 --- a/src/main/resources/pupper.accesswidener +++ /dev/null @@ -1,38 +0,0 @@ -accessWidener v2 named - -accessible class net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket$InteractType -accessible class net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket$InteractTypeHandler -accessible class net/minecraft/client/gui/hud/InGameHud$HeartType -accessible field net/minecraft/client/gui/screen/multiplayer/MultiplayerScreen serverListWidget Lnet/minecraft/client/gui/screen/multiplayer/MultiplayerServerListWidget; -accessible field net/minecraft/network/packet/c2s/play/ClientCommandC2SPacket mode Lnet/minecraft/network/packet/c2s/play/ClientCommandC2SPacket$Mode; -accessible method net/minecraft/client/network/ClientPlayerEntity sendSprintingPacket ()V -accessible field net/minecraft/client/network/ClientPlayerEntity lastSneaking Z -accessible method net/minecraft/client/network/ClientCommonNetworkHandler send (Lnet/minecraft/network/packet/Packet;Ljava/util/function/BooleanSupplier;Ljava/time/Duration;)V - -accessible field net/minecraft/util/PlayerInput jump Z -accessible field net/minecraft/util/PlayerInput sneak Z - -mutable field net/minecraft/util/PlayerInput jump Z -mutable field net/minecraft/util/PlayerInput sneak Z - -accessible field net/minecraft/network/packet/s2c/play/EntityVelocityUpdateS2CPacket velocityX I -accessible field net/minecraft/network/packet/s2c/play/EntityVelocityUpdateS2CPacket velocityY I -accessible field net/minecraft/network/packet/s2c/play/EntityVelocityUpdateS2CPacket velocityZ I - -mutable field net/minecraft/network/packet/s2c/play/EntityVelocityUpdateS2CPacket velocityX I -mutable field net/minecraft/network/packet/s2c/play/EntityVelocityUpdateS2CPacket velocityY I -mutable field net/minecraft/network/packet/s2c/play/EntityVelocityUpdateS2CPacket velocityZ I - -accessible field net/minecraft/client/MinecraftClient itemUseCooldown I -accessible method net/minecraft/client/MinecraftClient doItemUse ()V -accessible method net/minecraft/client/MinecraftClient doAttack ()Z - -accessible method net/minecraft/entity/LivingEntity calcGlidingVelocity (Lnet/minecraft/util/math/Vec3d;)Lnet/minecraft/util/math/Vec3d; -accessible field net/minecraft/client/gui/hud/InGameHud HOTBAR_SELECTION_TEXTURE Lnet/minecraft/util/Identifier; -accessible field net/minecraft/client/gui/hud/InGameHud HOTBAR_ATTACK_INDICATOR_BACKGROUND_TEXTURE Lnet/minecraft/util/Identifier; -accessible field net/minecraft/client/gui/hud/InGameHud HOTBAR_ATTACK_INDICATOR_PROGRESS_TEXTURE Lnet/minecraft/util/Identifier; - -accessible method net/minecraft/client/render/entity/LivingEntityRenderer addFeature (Lnet/minecraft/client/render/entity/feature/FeatureRenderer;)Z -accessible field net/minecraft/client/render/entity/EntityRenderDispatcher renderers Ljava/util/Map; -accessible field net/minecraft/client/render/entity/LivingEntityRenderer features Ljava/util/List; -accessible field net/minecraft/client/render/entity/EntityRenderDispatcher modelRenderers Ljava/util/Map; diff --git a/src/main/resources/pupper.classtweaker b/src/main/resources/pupper.classtweaker new file mode 100644 index 0000000..cb862d2 --- /dev/null +++ b/src/main/resources/pupper.classtweaker @@ -0,0 +1,15 @@ +classTweaker v1 official + +# OldAnimationsMod +accessible class net/minecraft/client/gui/Gui$HeartType +accessible method net/minecraft/client/Minecraft startUseItem ()V + +# onHitDelayFix +accessible method net/minecraft/client/Minecraft startAttack ()Z + +# ExtendedRenderPipelineBuilder +accessible method com/mojang/blaze3d/pipeline/RenderPipeline$Builder ()V +accessible method com/mojang/blaze3d/pipeline/RenderPipeline$Builder withSnippet (Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet;)V + +# MixinMultiplayerScreen onRemoved +accessible field net/minecraft/client/gui/screens/multiplayer/JoinMultiplayerScreen serverSelectionList Lnet/minecraft/client/gui/screens/multiplayer/ServerSelectionList; diff --git a/src/main/resources/pupper.mixins.json b/src/main/resources/pupper.mixins.json index 8223db7..91e3a8b 100644 --- a/src/main/resources/pupper.mixins.json +++ b/src/main/resources/pupper.mixins.json @@ -3,6 +3,7 @@ "package": "cn.pupperclient.mixin.mixins", "compatibilityLevel": "JAVA_21", "client": [ + "accessors.GameRendererAccessor", "minecraft.client.MixinClientBrandRetriever", "minecraft.client.MixinKeyboard", "minecraft.client.MixinMinecraftClient", @@ -15,16 +16,17 @@ "minecraft.client.gui.MixinSplashScreen", "minecraft.client.gui.MixinTitleScreen", "minecraft.client.option.MixinKeyBinding", - "minecraft.client.render.BufferRendererAccessor", + "minecraft.client.render.GuiRendererMixin", + "minecraft.client.render.LightmapMixin", "minecraft.client.render.MixinCamera", "minecraft.client.render.MixinEntityRenderer", "minecraft.client.render.MixinGameRenderer", "minecraft.client.render.MixinHeldItemRenderer", "minecraft.client.render.MixinInGameHud", "minecraft.client.render.MixinInGameOverlayRenderer", - "minecraft.client.render.MixinLightmapTextureManager", "minecraft.client.render.PupperInGameHud", "minecraft.client.render.PupperScoreboard", + "minecraft.client.render.RenderPipelineMixin", "minecraft.client.sound.MixinSoundSystem", "minecraft.client.util.MixinWindow", "minecraft.entity.MixinAbstractClientPlayerEntity", @@ -32,7 +34,6 @@ "minecraft.entity.MixinLivingEntity", "minecraft.entity.MixinPlayerEntity", "minecraft.network.MixinClientConnection", - "minecraft.network.packet.PlayerInteractEntityC2SPacketAccessor", "minecraft.world.MixinBiome", "minecraft.world.MixinClientWorldProperties", "minecraft.world.MixinWorld", @@ -40,5 +41,8 @@ ], "injectors": { "defaultRequire": 1 - } + }, + "mixins": [ + "minecraft.entity.MixinAvatar" + ] }