From 0fd424d213484aaf70708e05ebf6131ac15c9fc9 Mon Sep 17 00:00:00 2001 From: wuritz Date: Sat, 30 May 2026 14:17:00 +0200 Subject: [PATCH 1/4] asd --- src/main/java/com/genyo/managers/combat/CombatManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/genyo/managers/combat/CombatManager.java b/src/main/java/com/genyo/managers/combat/CombatManager.java index 5fe767d..a2ec126 100644 --- a/src/main/java/com/genyo/managers/combat/CombatManager.java +++ b/src/main/java/com/genyo/managers/combat/CombatManager.java @@ -23,6 +23,8 @@ public class CombatManager { public HashMap popList = new HashMap<>(); + //asd + @EventHandler private void onAttackEntity(AttackEntityEvent event) { if (mc.player == null && mc.world == null) return; From 4bb5737bb13986878f4a716d2a8d254f902ac8b6 Mon Sep 17 00:00:00 2001 From: wuritz Date: Sat, 30 May 2026 14:17:41 +0200 Subject: [PATCH 2/4] asdasdasd --- src/main/java/com/genyo/managers/combat/CombatManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/genyo/managers/combat/CombatManager.java b/src/main/java/com/genyo/managers/combat/CombatManager.java index a2ec126..b2000e8 100644 --- a/src/main/java/com/genyo/managers/combat/CombatManager.java +++ b/src/main/java/com/genyo/managers/combat/CombatManager.java @@ -23,7 +23,8 @@ public class CombatManager { public HashMap popList = new HashMap<>(); - //asd + // + //wfsdfdsf @EventHandler private void onAttackEntity(AttackEntityEvent event) { From 8be77fd4d48b7fa58c7b9ff24c3bdd77f5cbf30a Mon Sep 17 00:00:00 2001 From: Sleeepyv Date: Sat, 30 May 2026 17:49:42 +0530 Subject: [PATCH 3/4] 1.21.11-initial --- build.gradle | 10 +- gradle.properties | 9 +- gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 45633 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 40 +- gradlew.bat | 25 +- src/main/java/com/genyo/Genyo.java | 4 +- .../com/genyo/commands/EnemiesCommand.java | 4 +- .../PlayerListEntryArgumentTypeEx.java | 6 +- .../com/genyo/core/render/Interpolation.java | 10 +- .../com/genyo/core/sound/SoundManager.java | 17 + .../genyo/managers/combat/CombatManager.java | 3 - .../managers/network/NetworkManager.java | 28 +- .../managers/player/InventoryManager.java | 83 +- .../managers/player/MovementManager.java | 39 +- .../managers/player/PositionManager.java | 19 +- .../accessor/AccessorClientConnection.java | 7 +- ...AccessorEntityVelocityUpdateS2CPacket.java | 14 +- .../genyo/mixin/accessor/AccessorInput.java | 18 + .../com/genyo/mixin/entity/MixinEntity.java | 4 +- .../entity/player/MixinPlayerListEntry.java | 44 +- .../game/MixinSplashTextResourceSupplier.java | 3 +- .../genyo/mixin/game/MixinTitleScreen.java | 8 +- .../genyo/mixin/meteor/MixinBetterTab.java | 2 +- .../com/genyo/mixin/meteor/MixinWWidget.java | 57 + .../MixinClientPlayNetworkHandler.java | 2 +- .../network/MixinClientPlayerEntity.java | 44 +- .../mixin/render/MixinRenderTickCounter.java | 20 +- .../mixin/render/MixinWorldRenderer.java | 10 +- .../java/com/genyo/render/Render2DEngine.java | 9 +- .../java/com/genyo/render/Render3DEngine.java | 714 +-------- .../com/genyo/systems/config/GenyoConfig.java | 29 +- .../com/genyo/systems/enemies/Enemies.java | 10 +- .../java/com/genyo/systems/enemies/Enemy.java | 7 +- .../com/genyo/systems/hud/GenyoTargetHud.java | 582 ++++++++ .../java/com/genyo/systems/hud/LogoHud.java | 10 +- .../systems/modules/combat/AutoCrawlTrap.java | 4 +- .../systems/modules/combat/BasePlace.java | 3 +- .../modules/combat/FriendProtector.java | 2 +- .../modules/combat/GenyoAutoArmor.java | 9 +- .../modules/combat/GenyoAutoCrystal.java | 42 +- .../modules/combat/GenyoAutoTotem.java | 4 +- .../systems/modules/combat/GenyoAutoTrap.java | 2 +- .../systems/modules/combat/GenyoAutoXP.java | 3 +- .../systems/modules/combat/KFCSpawnKill.java | 26 +- .../systems/modules/misc/AutoOminous.java | 4 +- .../systems/modules/misc/AutoRename.java | 4 +- .../systems/modules/misc/CombatBrainrot.java | 2 +- .../systems/modules/misc/GenyoAutoEZ.java | 2 +- .../systems/modules/misc/GenyoDiscord.java | 2 +- .../systems/modules/misc/GenyoGoodbye.java | 2 +- .../systems/modules/misc/GenyoWelcome.java | 6 +- .../systems/modules/movement/GenyoNoSlow.java | 44 +- .../systems/modules/movement/GenyoPhase.java | 4 +- .../modules/movement/GenyoVelocity.java | 33 +- .../modules/movement/TsunodaBlinker.java | 2 +- .../modules/visual/AngelSexHulkenberg.java | 259 ---- .../systems/modules/visual/GenyoCapes.java | 30 +- .../systems/modules/visual/GenyoNametags.java | 16 +- .../systems/modules/visual/Parkinsons.java | 6 +- .../systems/modules/visual/PenisESP.java | 6 +- .../systems/modules/world/AutoMineV2.java | 334 ----- .../systems/modules/world/GenyoAutoMine.java | 7 +- .../modules/world/GenyoAutoMineV2.java | 1274 +++++++++++++++++ .../systems/modules/world/GenyoAutoTool.java | 2 +- .../systems/modules/world/GenyoSelfTrap.java | 99 +- .../modules/world/GenyoSurroundV2.java | 99 +- .../genyo/systems/settings/FloatSetting.java | 2 +- .../settings/playerlist/ListPlayer.java | 7 +- .../playerlist/PlayerListGroupSetting.java | 6 +- src/main/java/com/genyo/utils/GInvUtils.java | 12 +- src/main/java/com/genyo/utils/HudUtils.java | 10 +- .../genyo/utils/player/InteractionUtil.java | 123 +- .../com/genyo/utils/player/MovementUtil.java | 36 +- .../genyo/utils/player/SearchInvResult.java | 2 +- .../genyo/utils/render/SInterpolation.java | 28 +- .../com/genyo/utils/world/ExplosionUtil.java | 33 +- src/main/resources/assets/genyo/sounds.json | 15 + .../assets/genyo/sounds/gui_click_left.ogg | Bin 0 -> 7133 bytes .../assets/genyo/sounds/gui_click_right.ogg | Bin 0 -> 5409 bytes .../assets/genyo/sounds/gui_hover.ogg | Bin 0 -> 5432 bytes .../assets/genyo/textures/cape_dev.png | Bin 0 -> 45801 bytes src/main/resources/fabric.mod.json | 3 +- src/main/resources/genyo.accesswidener | 6 +- src/main/resources/genyo.mixins.json | 2 + 85 files changed, 2687 insertions(+), 1823 deletions(-) create mode 100644 src/main/java/com/genyo/mixin/accessor/AccessorInput.java create mode 100644 src/main/java/com/genyo/mixin/meteor/MixinWWidget.java create mode 100644 src/main/java/com/genyo/systems/hud/GenyoTargetHud.java delete mode 100644 src/main/java/com/genyo/systems/modules/visual/AngelSexHulkenberg.java delete mode 100644 src/main/java/com/genyo/systems/modules/world/AutoMineV2.java create mode 100644 src/main/java/com/genyo/systems/modules/world/GenyoAutoMineV2.java create mode 100644 src/main/resources/assets/genyo/sounds/gui_click_left.ogg create mode 100644 src/main/resources/assets/genyo/sounds/gui_click_right.ogg create mode 100644 src/main/resources/assets/genyo/sounds/gui_hover.ogg create mode 100644 src/main/resources/assets/genyo/textures/cape_dev.png diff --git a/build.gradle b/build.gradle index ecc5bfd..480b084 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id 'base' - id "fabric-loom" version "1.11-SNAPSHOT" + id "fabric-loom" version "1.14-SNAPSHOT" } version = project.mod_version @@ -35,7 +35,7 @@ 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 fabricApi.module("fabric-registry-sync-v0", "0.119.4+1.21.4") + modImplementation fabricApi.module("fabric-registry-sync-v0", "0.139.5+1.21.11") // Meteor modImplementation "meteordevelopment:meteor-client:${project.minecraft_version}-SNAPSHOT" @@ -46,6 +46,12 @@ dependencies { implementation "com.ferra13671:discord-ipc:1.2" include 'com.ferra13671:discord-ipc:1.2' + + // Jackson + implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' + include 'com.fasterxml.jackson.core:jackson-databind:2.15.2' + + } tasks { diff --git a/gradle.properties b/gradle.properties index 33572a3..d33ba4c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,13 @@ org.gradle.jvmargs=-Xmx2G +org.gradle.configuration-cache=false # Fabric Properties (https://fabricmc.net/develop) -minecraft_version=1.21.4 -yarn_mappings=1.21.4+build.8 -loader_version=0.16.4 +minecraft_version=1.21.11 +yarn_mappings=1.21.11+build.3 +loader_version=0.18.2 # Mod Properties -mod_version=1.1.1 +mod_version=2.0.0 maven_group=com.genyo archives_base_name=genyo-addon diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..f8e1ee3125fe0768e9a76ee977ac089eb657005e 100644 GIT binary patch literal 45633 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�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 literal 61574 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

Genyo Addon

❤꧁ღ⊱♥ I have brain damge ♥⊱ღ꧂❤

-

Shoreline port into Meteor 1.21.4 plus other GENYO magic :D

+

Shoreline port into Meteor 1.21.11 plus other GENYO magic :D

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 ScNgau(U?ep-K_E5zy1%ZQTdPn diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ca025c8..bad7c24 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-8.14-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 65dcd68..adff685 100755 --- 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. @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/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/. @@ -83,10 +85,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# 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\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -114,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. @@ -133,10 +132,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +146,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +154,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -169,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" ) @@ -197,16 +198,19 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * 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 93e3f59..c4bdd3a 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,22 +59,21 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 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/src/main/java/com/genyo/Genyo.java b/src/main/java/com/genyo/Genyo.java index bf10dda..422f1a3 100644 --- a/src/main/java/com/genyo/Genyo.java +++ b/src/main/java/com/genyo/Genyo.java @@ -134,7 +134,6 @@ private void initSystems() { private void initModules(Modules modules) { modules.add(new GenyoAutoEZ()); - modules.add(new AngelSexHulkenberg()); modules.add(new GenyoSurround()); modules.add(new GenyoWelcome()); modules.add(new GenyoSkinBlink()); @@ -156,6 +155,7 @@ private void initModules(Modules modules) { modules.add(new CombatBrainrot()); modules.add(new PacketDebug()); modules.add(new GenyoAutoMine()); + modules.add(new GenyoAutoMineV2()); modules.add(new GenyoAutoXP()); modules.add(new GenyoAutoArmor()); modules.add(new GenyoAutoTrap()); @@ -193,6 +193,7 @@ private void initHUD(Hud hud) { hud.register(BetterPlayerRadarHud.INFO); hud.register(LogoHud.INFO); hud.register(PingHud.INFO); + hud.register(GenyoTargetHud.INFO); HUD_ELEMENTS.add(PvPNeccessaryHud.INFO); HUD_ELEMENTS.add(ActiveGenyoHud.INFO); @@ -201,6 +202,7 @@ private void initHUD(Hud hud) { HUD_ELEMENTS.add(BetterPlayerRadarHud.INFO); HUD_ELEMENTS.add(LogoHud.INFO); HUD_ELEMENTS.add(PingHud.INFO); + HUD_ELEMENTS.add(GenyoTargetHud.INFO); } @Override diff --git a/src/main/java/com/genyo/commands/EnemiesCommand.java b/src/main/java/com/genyo/commands/EnemiesCommand.java index 705c8bb..d99ad13 100644 --- a/src/main/java/com/genyo/commands/EnemiesCommand.java +++ b/src/main/java/com/genyo/commands/EnemiesCommand.java @@ -23,12 +23,12 @@ public void build(LiteralArgumentBuilder builder) { .then((argument("player", PlayerListEntryArgumentTypeEx.create()) .executes(context -> { GameProfile profile = PlayerListEntryArgumentTypeEx.get(context).getProfile(); - if (profile.getName().equals(mc.player.getGameProfile().getName())) { + if (profile.name().equals(mc.player.getGameProfile().name())) { GenyoChatUtils.sendError("You can't add yourself as enemy."); return SINGLE_SUCCESS; } - Enemy enemy = new Enemy(profile.getName(), profile.getId()); + Enemy enemy = new Enemy(profile.name(), profile.id()); if (Enemies.get().add(enemy)) { GenyoChatUtils.sendMessage(Formatting.GRAY + "Added %s to enemies.".formatted(enemy.getName())); diff --git a/src/main/java/com/genyo/commands/arguments/PlayerListEntryArgumentTypeEx.java b/src/main/java/com/genyo/commands/arguments/PlayerListEntryArgumentTypeEx.java index 8e1ce20..19b2e77 100644 --- a/src/main/java/com/genyo/commands/arguments/PlayerListEntryArgumentTypeEx.java +++ b/src/main/java/com/genyo/commands/arguments/PlayerListEntryArgumentTypeEx.java @@ -39,7 +39,7 @@ public PlayerListEntry parse(StringReader reader) throws CommandSyntaxException PlayerListEntry playerListEntry = null; for (PlayerListEntry p : mc.getNetworkHandler().getPlayerList()) { - if (p.getProfile().getName().equalsIgnoreCase(argument)) { + if (p.getProfile().name().equalsIgnoreCase(argument)) { playerListEntry = p; break; } @@ -52,12 +52,12 @@ public PlayerListEntry parse(StringReader reader) throws CommandSyntaxException @Override public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { Collection playerListEntries = mc.getNetworkHandler().getPlayerList(); - PlayerListEntry clientEntry = mc.getNetworkHandler().getPlayerListEntry(mc.player.getGameProfile().getName()); + PlayerListEntry clientEntry = mc.getNetworkHandler().getPlayerListEntry(mc.player.getGameProfile().name()); if (playerListEntries.contains(clientEntry)) playerListEntries.remove(clientEntry); // just made this to exclude yourself from the list, it was kinda annoying. - return CommandSource.suggestMatching(playerListEntries.stream().map(playerListEntry -> playerListEntry.getProfile().getName()), builder); + return CommandSource.suggestMatching(playerListEntries.stream().map(playerListEntry -> playerListEntry.getProfile().name()), builder); } @Override diff --git a/src/main/java/com/genyo/core/render/Interpolation.java b/src/main/java/com/genyo/core/render/Interpolation.java index fbc86b2..173b600 100644 --- a/src/main/java/com/genyo/core/render/Interpolation.java +++ b/src/main/java/com/genyo/core/render/Interpolation.java @@ -38,9 +38,9 @@ public static Vec3d getRenderPosition(Entity entity, float tickDelta) */ public static Vec3d getInterpolatedPosition(Entity entity, float tickDelta) { - return new Vec3d(entity.prevX + ((entity.getX() - entity.prevX) * tickDelta), - entity.prevY + ((entity.getY() - entity.prevY) * tickDelta), - entity.prevZ + ((entity.getZ() - entity.prevZ) * tickDelta)); + return new Vec3d(entity.lastX + ((entity.getX() - entity.lastX) * tickDelta), + entity.lastY + ((entity.getY() - entity.lastY) * tickDelta), + entity.lastZ + ((entity.getZ() - entity.lastZ) * tickDelta)); } /** @@ -73,7 +73,7 @@ public static double interpolateDouble(double prev, double value, double factor) public static Box getInterpolatedBox(Box prevBox, Box box) { - double delta = mc.isPaused() ? 1f : mc.getRenderTickCounter().getTickDelta(true); + double delta = mc.isPaused() ? 1f : mc.getRenderTickCounter().getTickProgress(true); return new Box(interpolateDouble(prevBox.minX, box.minX, delta), interpolateDouble(prevBox.minY, box.minY, delta), @@ -90,7 +90,7 @@ public static Box getInterpolatedBox(Box prevBox, Box box) public static Box getInterpolatedEntityBox(Entity entity) { Box box = entity.getBoundingBox(); - Box prevBox = entity.getBoundingBox().offset(entity.prevX - entity.getX(), entity.prevY - entity.getY(), entity.prevZ - entity.getZ()); + Box prevBox = entity.getBoundingBox().offset(entity.lastX - entity.getX(), entity.lastY - entity.getY(), entity.lastZ - entity.getZ()); return getInterpolatedBox(prevBox, box); } diff --git a/src/main/java/com/genyo/core/sound/SoundManager.java b/src/main/java/com/genyo/core/sound/SoundManager.java index 718a65d..64039a7 100644 --- a/src/main/java/com/genyo/core/sound/SoundManager.java +++ b/src/main/java/com/genyo/core/sound/SoundManager.java @@ -10,6 +10,15 @@ public class SoundManager { + public static final Identifier GUI_HOVER_ID = Identifier.of("genyo:gui_hover"); + public static final SoundEvent GUI_HOVER = SoundEvent.of(GUI_HOVER_ID); + + public static final Identifier GUI_CLICK_LEFT_ID = Identifier.of("genyo:gui_click_left"); + public static final SoundEvent GUI_CLICK_LEFT = SoundEvent.of(GUI_CLICK_LEFT_ID); + + public static final Identifier GUI_CLICK_RIGHT_ID = Identifier.of("genyo:gui_click_right"); + public static final SoundEvent GUI_CLICK_RIGHT = SoundEvent.of(GUI_CLICK_RIGHT_ID); + public static final Identifier VINE_ID = Identifier.of("genyo:vine"); public static final SoundEvent VINE = SoundEvent.of(VINE_ID); @@ -31,6 +40,11 @@ public class SoundManager { public static final Identifier KIWI_ID = Identifier.of("genyo:kiwi"); public static final SoundEvent KIWI = SoundEvent.of(KIWI_ID); + public void playUISound(SoundEvent sound, float volume, float pitch) { + mc.getSoundManager().play( + net.minecraft.client.sound.PositionedSoundInstance.master(sound, pitch, volume) + ); + } public void playSound(SoundEvent sound) { if (mc.player != null && mc.world != null && GenyoConfig.get() != null) { mc.player.playSound(sound, (float) GenyoConfig.get().globalVolume.get() / 100f, 1f); @@ -57,6 +71,9 @@ public static void init() { Registry.register(Registries.SOUND_EVENT, BLACK_ID, BLACK); Registry.register(Registries.SOUND_EVENT, KEYPRESS_ID, KEYPRESS); Registry.register(Registries.SOUND_EVENT, KIWI_ID, KIWI); + Registry.register(Registries.SOUND_EVENT, GUI_HOVER_ID, GUI_HOVER); + Registry.register(Registries.SOUND_EVENT, GUI_CLICK_LEFT_ID, GUI_CLICK_LEFT); + Registry.register(Registries.SOUND_EVENT, GUI_CLICK_RIGHT_ID, GUI_CLICK_RIGHT); } } diff --git a/src/main/java/com/genyo/managers/combat/CombatManager.java b/src/main/java/com/genyo/managers/combat/CombatManager.java index b2000e8..5fe767d 100644 --- a/src/main/java/com/genyo/managers/combat/CombatManager.java +++ b/src/main/java/com/genyo/managers/combat/CombatManager.java @@ -23,9 +23,6 @@ public class CombatManager { public HashMap popList = new HashMap<>(); - // - //wfsdfdsf - @EventHandler private void onAttackEntity(AttackEntityEvent event) { if (mc.player == null && mc.world == null) return; diff --git a/src/main/java/com/genyo/managers/network/NetworkManager.java b/src/main/java/com/genyo/managers/network/NetworkManager.java index cb906d3..2fbad9e 100644 --- a/src/main/java/com/genyo/managers/network/NetworkManager.java +++ b/src/main/java/com/genyo/managers/network/NetworkManager.java @@ -8,6 +8,7 @@ import meteordevelopment.meteorclient.events.packets.PacketEvent; import meteordevelopment.orbit.EventHandler; import net.minecraft.client.network.*; +import net.minecraft.client.world.ClientChunkLoadProgress; import net.minecraft.network.listener.ServerPlayPacketListener; import net.minecraft.network.packet.Packet; @@ -51,14 +52,23 @@ public void onPacketReceive(PacketEvent.Receive event) incomingCounter.updateCounter(); } - public void connect(final ServerAddress address, final ServerInfo info) - { - if (mc.getNetworkHandler() == null) - { - return; - } - mc.getNetworkHandler().getConnection().connect(address.getAddress(), address.getPort(), - new ClientLoginNetworkHandler(mc.getNetworkHandler().getConnection(), mc, info, null, false, null, null, null)); + public void connect(final ServerAddress address, final ServerInfo info) { + if (mc.getNetworkHandler() == null) return; + mc.getNetworkHandler().getConnection().connect( + address.getAddress(), + address.getPort(), + new ClientLoginNetworkHandler( + mc.getNetworkHandler().getConnection(), + mc, + info, + null, + false, + null, + text -> {}, + new ClientChunkLoadProgress(), + null + ) + ); } public void sendQuietPacket(final Packet p) @@ -129,7 +139,7 @@ public int getClientLatency() if (mc.getNetworkHandler() != null) { final PlayerListEntry playerEntry = - mc.getNetworkHandler().getPlayerListEntry(mc.player.getGameProfile().getId()); + mc.getNetworkHandler().getPlayerListEntry(mc.player.getGameProfile().id()); if (playerEntry != null) { return playerEntry.getLatency(); diff --git a/src/main/java/com/genyo/managers/player/InventoryManager.java b/src/main/java/com/genyo/managers/player/InventoryManager.java index 6bf5d1e..fbd52f3 100644 --- a/src/main/java/com/genyo/managers/player/InventoryManager.java +++ b/src/main/java/com/genyo/managers/player/InventoryManager.java @@ -23,6 +23,8 @@ import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.screen.sync.ComponentChangesHash; +import net.minecraft.screen.sync.ItemStackHash; import net.minecraft.util.collection.DefaultedList; import java.util.ArrayList; @@ -176,7 +178,7 @@ public void setSlotAlt(final int barSlot) */ public void setClientSlot(final int barSlot) { - if (mc.player.getInventory().selectedSlot != barSlot + if (mc.player.getInventory().getSelectedSlot() != barSlot && PlayerInventory.isValidHotbarIndex(barSlot)) { mc.player.getInventory().setSelectedSlot(barSlot); @@ -201,7 +203,7 @@ public void syncToClient() { if (isDesynced()) { - setSlotForced(mc.player.getInventory().selectedSlot); + setSlotForced(mc.player.getInventory().getSelectedSlot()); for (PreSwapData swapData : swapData) { @@ -212,7 +214,7 @@ public void syncToClient() public boolean isDesynced() { - return mc.player.getInventory().selectedSlot != slot; + return mc.player.getInventory().getSelectedSlot() != slot; } // @@ -260,57 +262,68 @@ public int findEmptySlot() * @param button * @param type */ - public int click(int slot, int button, SlotActionType type) - { - if (slot < 0) - { - return -1; - } + public int click(int slot, int button, SlotActionType type) { + if (slot < 0) return -1; + ScreenHandler screenHandler = mc.player.currentScreenHandler; DefaultedList defaultedList = screenHandler.slots; int i = defaultedList.size(); ArrayList list = Lists.newArrayListWithCapacity(i); - for (Slot slot1 : defaultedList) - { + for (Slot slot1 : defaultedList) { list.add(slot1.getStack().copy()); } screenHandler.onSlotClick(slot, button, type, mc.player); - Int2ObjectOpenHashMap int2ObjectMap = new Int2ObjectOpenHashMap<>(); - for (int j = 0; j < i; ++j) - { - ItemStack itemStack2; + + ComponentChangesHash.ComponentHasher hasher = component -> component.value().hashCode(); + Int2ObjectOpenHashMap int2ObjectMap = new Int2ObjectOpenHashMap<>(); + for (int j = 0; j < i; ++j) { ItemStack itemStack = list.get(j); - if (ItemStack.areEqual(itemStack, itemStack2 = defaultedList.get(j).getStack())) continue; - int2ObjectMap.put(j, itemStack2.copy()); + ItemStack itemStack2 = defaultedList.get(j).getStack(); + if (ItemStack.areEqual(itemStack, itemStack2)) continue; + int2ObjectMap.put(j, ItemStackHash.fromItemStack(itemStack2, hasher)); } - mc.player.networkHandler.sendPacket(new ClickSlotC2SPacket(screenHandler.syncId, screenHandler.getRevision(), slot, button, type, screenHandler.getCursorStack().copy(), int2ObjectMap)); + + mc.player.networkHandler.sendPacket(new ClickSlotC2SPacket( + screenHandler.syncId, + screenHandler.getRevision(), + (short) slot, + (byte) button, + type, + int2ObjectMap, + ItemStackHash.fromItemStack(screenHandler.getCursorStack(), hasher) + )); return screenHandler.getRevision(); } - public int click2(int slot, int button, SlotActionType type) - { - if (slot < 0) - { - return -1; - } + public int click2(int slot, int button, SlotActionType type) { + if (slot < 0) return -1; + ScreenHandler screenHandler = mc.player.currentScreenHandler; DefaultedList defaultedList = screenHandler.slots; int i = defaultedList.size(); ArrayList list = Lists.newArrayListWithCapacity(i); - for (Slot slot1 : defaultedList) - { + for (Slot slot1 : defaultedList) { list.add(slot1.getStack().copy()); } - // screenHandler.onSlotClick(slot, button, type, mc.player); - Int2ObjectOpenHashMap int2ObjectMap = new Int2ObjectOpenHashMap<>(); - for (int j = 0; j < i; ++j) - { - ItemStack itemStack2; + + ComponentChangesHash.ComponentHasher hasher = component -> component.value().hashCode(); + Int2ObjectOpenHashMap int2ObjectMap = new Int2ObjectOpenHashMap<>(); + for (int j = 0; j < i; ++j) { ItemStack itemStack = list.get(j); - if (ItemStack.areEqual(itemStack, itemStack2 = defaultedList.get(j).getStack())) continue; - int2ObjectMap.put(j, itemStack2.copy()); + ItemStack itemStack2 = defaultedList.get(j).getStack(); + if (ItemStack.areEqual(itemStack, itemStack2)) continue; + int2ObjectMap.put(j, ItemStackHash.fromItemStack(itemStack2, hasher)); } - mc.player.networkHandler.sendPacket(new ClickSlotC2SPacket(screenHandler.syncId, screenHandler.getRevision(), slot, button, type, screenHandler.getCursorStack().copy(), int2ObjectMap)); + + mc.player.networkHandler.sendPacket(new ClickSlotC2SPacket( + screenHandler.syncId, + screenHandler.getRevision(), + (short) slot, + (byte) button, + type, + int2ObjectMap, + ItemStackHash.fromItemStack(screenHandler.getCursorStack(), hasher) + )); return screenHandler.getRevision(); } @@ -324,7 +337,7 @@ public int getServerSlot() public int getClientSlot() { - return mc.player.getInventory().selectedSlot; + return mc.player.getInventory().getSelectedSlot(); } /** diff --git a/src/main/java/com/genyo/managers/player/MovementManager.java b/src/main/java/com/genyo/managers/player/MovementManager.java index 77a2339..26828e8 100644 --- a/src/main/java/com/genyo/managers/player/MovementManager.java +++ b/src/main/java/com/genyo/managers/player/MovementManager.java @@ -1,62 +1,37 @@ package com.genyo.managers.player; import com.genyo.events.network.PacketSneakingEvent; -import com.genyo.managers.Managers; import meteordevelopment.orbit.EventHandler; -import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket; import static meteordevelopment.meteorclient.MeteorClient.mc; -import static net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY; -import static net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY; public class MovementManager { private boolean packetSneaking; - /** - * @param y - */ - public void setMotionY(double y) - { + public void setMotionY(double y) { mc.player.setVelocity(mc.player.getVelocity().getX(), y, mc.player.getVelocity().getZ()); } - /** - * @param x - * @param z - */ - public void setMotionXZ(double x, double z) - { + public void setMotionXZ(double x, double z) { mc.player.setVelocity(x, mc.player.getVelocity().y, z); } - public void setMotionX(double x) - { + public void setMotionX(double x) { mc.player.setVelocity(x, mc.player.getVelocity().y, mc.player.getVelocity().z); } - public void setMotionZ(double z) - { + public void setMotionZ(double z) { mc.player.setVelocity(mc.player.getVelocity().x, mc.player.getVelocity().y, z); } - - public void setPacketSneaking(final boolean packetSneaking) - { + public void setPacketSneaking(final boolean packetSneaking) { this.packetSneaking = packetSneaking; - if (packetSneaking) - { - Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, PRESS_SHIFT_KEY)); - } - else - { - Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, RELEASE_SHIFT_KEY)); - } + mc.player.setSneaking(packetSneaking); } @EventHandler - public void onPacketSneak(PacketSneakingEvent event) - { + public void onPacketSneak(PacketSneakingEvent event) { event.setCancelled(packetSneaking); } diff --git a/src/main/java/com/genyo/managers/player/PositionManager.java b/src/main/java/com/genyo/managers/player/PositionManager.java index b89a511..c9712de 100644 --- a/src/main/java/com/genyo/managers/player/PositionManager.java +++ b/src/main/java/com/genyo/managers/player/PositionManager.java @@ -18,7 +18,7 @@ public class PositionManager { private double x, y, z; private BlockPos blockPos; // - private boolean sneaking, sprinting; + private boolean sprinting; // private boolean onGround; private boolean horizontalCollision; @@ -102,10 +102,10 @@ public Vec3d getEyePos() */ public final Vec3d getCameraPosVec(float tickDelta) { - double d = MathHelper.lerp(tickDelta, mc.player.prevX, getX()); - double e = MathHelper.lerp(tickDelta, mc.player.prevY, getY()) + double d = MathHelper.lerp(tickDelta, mc.player.lastX, getX()); + double e = MathHelper.lerp(tickDelta, mc.player.lastY, getY()) + (double) mc.player.getStandingEyeHeight(); - double f = MathHelper.lerp(tickDelta, mc.player.prevZ, getZ()); + double f = MathHelper.lerp(tickDelta, mc.player.lastZ, getZ()); return new Vec3d(d, e, f); } @@ -160,8 +160,6 @@ else if (event.packet instanceof ClientCommandC2SPacket packet) { case START_SPRINTING -> sprinting = true; case STOP_SPRINTING -> sprinting = false; - case PRESS_SHIFT_KEY -> sneaking = true; - case RELEASE_SHIFT_KEY -> sneaking = false; } } } @@ -190,13 +188,12 @@ public BlockPos getBlockPos() return blockPos; } + public boolean isSneaking() { + return mc.player != null && mc.player.isSneaking(); + } + /** * @return - */ - public boolean isSneaking() - { - return sneaking; - } /** * @return diff --git a/src/main/java/com/genyo/mixin/accessor/AccessorClientConnection.java b/src/main/java/com/genyo/mixin/accessor/AccessorClientConnection.java index a3e9be2..1491794 100644 --- a/src/main/java/com/genyo/mixin/accessor/AccessorClientConnection.java +++ b/src/main/java/com/genyo/mixin/accessor/AccessorClientConnection.java @@ -1,16 +1,15 @@ package com.genyo.mixin.accessor; +import io.netty.channel.ChannelFutureListener; import net.minecraft.network.ClientConnection; -import net.minecraft.network.PacketCallbacks; import net.minecraft.network.packet.Packet; +import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -import javax.annotation.Nullable; - @Mixin(ClientConnection.class) public interface AccessorClientConnection { @Invoker("sendInternal") - void hookSendInternal(Packet packet, @Nullable PacketCallbacks callbacks, boolean flush); + void hookSendInternal(Packet packet, @Nullable ChannelFutureListener listener, boolean flush); } diff --git a/src/main/java/com/genyo/mixin/accessor/AccessorEntityVelocityUpdateS2CPacket.java b/src/main/java/com/genyo/mixin/accessor/AccessorEntityVelocityUpdateS2CPacket.java index 240d66d..2e92b64 100644 --- a/src/main/java/com/genyo/mixin/accessor/AccessorEntityVelocityUpdateS2CPacket.java +++ b/src/main/java/com/genyo/mixin/accessor/AccessorEntityVelocityUpdateS2CPacket.java @@ -1,6 +1,7 @@ package com.genyo.mixin.accessor; import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket; +import net.minecraft.util.math.Vec3d; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; @@ -8,15 +9,10 @@ @Mixin(EntityVelocityUpdateS2CPacket.class) public interface AccessorEntityVelocityUpdateS2CPacket { - @Accessor("velocityX") - @Mutable - void setVelocityX(int velocityX); - - @Accessor("velocityY") - @Mutable - void setVelocityY(int velocityY); + @Accessor("velocity") + Vec3d getVelocity(); - @Accessor("velocityZ") + @Accessor("velocity") @Mutable - void setVelocityZ(int velocityZ); + void setVelocity(Vec3d velocity); } diff --git a/src/main/java/com/genyo/mixin/accessor/AccessorInput.java b/src/main/java/com/genyo/mixin/accessor/AccessorInput.java new file mode 100644 index 0000000..427e777 --- /dev/null +++ b/src/main/java/com/genyo/mixin/accessor/AccessorInput.java @@ -0,0 +1,18 @@ +package com.genyo.mixin.accessor; + +import net.minecraft.client.input.Input; +import net.minecraft.util.math.Vec2f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Input.class) +public interface AccessorInput { + @Accessor("movementVector") + Vec2f getMovementVector(); + + @Mutable + @Accessor("movementVector") + void setMovementVector(Vec2f vec); +} + diff --git a/src/main/java/com/genyo/mixin/entity/MixinEntity.java b/src/main/java/com/genyo/mixin/entity/MixinEntity.java index 8a9a7f0..b4e28c5 100644 --- a/src/main/java/com/genyo/mixin/entity/MixinEntity.java +++ b/src/main/java/com/genyo/mixin/entity/MixinEntity.java @@ -22,7 +22,7 @@ public class MixinEntity { @Shadow - public float fallDistance; + public double fallDistance; @Shadow protected Vec3d movementMultiplier; @@ -55,7 +55,7 @@ private void hookSlowMovement(BlockState state, Vec3d multiplier, CallbackInfo c MeteorClient.EVENT_BUS.post(slowMovementEvent); if (slowMovementEvent.isCancelled()) { ci.cancel(); - this.fallDistance = 0.0f; + this.fallDistance = 0.0; this.movementMultiplier = multiplier.multiply(slowMovementEvent.multiplier); } } diff --git a/src/main/java/com/genyo/mixin/entity/player/MixinPlayerListEntry.java b/src/main/java/com/genyo/mixin/entity/player/MixinPlayerListEntry.java index f037eda..f7414a8 100644 --- a/src/main/java/com/genyo/mixin/entity/player/MixinPlayerListEntry.java +++ b/src/main/java/com/genyo/mixin/entity/player/MixinPlayerListEntry.java @@ -4,7 +4,8 @@ import com.mojang.authlib.GameProfile; import meteordevelopment.meteorclient.systems.modules.Modules; import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.util.SkinTextures; +import net.minecraft.entity.player.SkinTextures; +import net.minecraft.util.AssetInfo; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -24,16 +25,37 @@ public abstract class MixinPlayerListEntry { @Inject(method = "getSkinTextures", at = @At("TAIL"), cancellable = true) private void getSkinTextures(CallbackInfoReturnable info) { - if (((profile.getName().equals(mc.player.getGameProfile().getName()) - && profile.getId().equals(mc.player.getGameProfile().getId()))) - && Modules.get().isActive(GenyoCapes.class) - && Modules.get().get(GenyoCapes.class).getCapeTexture() != null) - { - Identifier identifier = Modules.get().get(GenyoCapes.class).getCapeTexture(); - SkinTextures texture = info.getReturnValue(); - - info.setReturnValue(new SkinTextures(texture.texture(), texture.textureUrl(), identifier, identifier, texture.model(), texture.secure())); + if (!Modules.get().isActive(GenyoCapes.class)) return; + + GenyoCapes mod = Modules.get().get(GenyoCapes.class); + String name = profile.name(); + + boolean isSelf = name.equals(mc.player.getGameProfile().name()) + && profile.id().equals(mc.player.getGameProfile().id()); + boolean isDev = mod.isDev(name); + + if (!isDev && !isSelf && !mod.everyoneConfig.get()) return; + + Identifier textureId; + Identifier texturePath; + + if (isDev) { + textureId = Identifier.of("genyo", "cape_dev"); + texturePath = Identifier.of("genyo", "textures/cape_dev.png"); + } else { + textureId = Identifier.of("genyo", "cape"); + texturePath = Identifier.of("genyo", "textures/cape.png"); } - } + SkinTextures original = info.getReturnValue(); + AssetInfo.TextureAssetInfo capeAsset = new AssetInfo.TextureAssetInfo(textureId, texturePath); + + info.setReturnValue(new SkinTextures( + original.body(), + capeAsset, + capeAsset, + original.model(), + original.secure() + )); + } } diff --git a/src/main/java/com/genyo/mixin/game/MixinSplashTextResourceSupplier.java b/src/main/java/com/genyo/mixin/game/MixinSplashTextResourceSupplier.java index b219ea0..2e65a4d 100644 --- a/src/main/java/com/genyo/mixin/game/MixinSplashTextResourceSupplier.java +++ b/src/main/java/com/genyo/mixin/game/MixinSplashTextResourceSupplier.java @@ -3,6 +3,7 @@ import com.genyo.systems.config.GenyoConfig; import net.minecraft.client.gui.screen.SplashTextRenderer; import net.minecraft.client.resource.SplashTextResourceSupplier; +import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -26,7 +27,7 @@ public abstract class MixinSplashTextResourceSupplier { private void onApply(CallbackInfoReturnable cir) { if (GenyoConfig.get() == null || !GenyoConfig.get().useGenyoSplashes.get()) return; - if (override) cir.setReturnValue(new SplashTextRenderer(splashes.get(random.nextInt(splashes.size())))); + if (override) cir.setReturnValue(new SplashTextRenderer(Text.literal(splashes.get(random.nextInt(splashes.size()))))); override = !override; } diff --git a/src/main/java/com/genyo/mixin/game/MixinTitleScreen.java b/src/main/java/com/genyo/mixin/game/MixinTitleScreen.java index 9e1a20d..2e57726 100644 --- a/src/main/java/com/genyo/mixin/game/MixinTitleScreen.java +++ b/src/main/java/com/genyo/mixin/game/MixinTitleScreen.java @@ -1,11 +1,11 @@ package com.genyo.mixin.game; import com.genyo.core.Changelog; +import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.text.Text; -import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -25,9 +25,9 @@ private void onRender(DrawContext context, int mouseX, int mouseY, float delta, } @Inject(method = "mouseClicked", at = @At("HEAD"), cancellable = true) - private void onMouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable info) { - if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { - if (Changelog.onClicked(mouseX, mouseY)) info.setReturnValue(true); + private void onMouseClicked(Click click, boolean bl, CallbackInfoReturnable info) { + if (click.button() == 0) { // 0 = left mouse button + if (Changelog.onClicked(click.x(), click.y())) info.setReturnValue(true); } } } diff --git a/src/main/java/com/genyo/mixin/meteor/MixinBetterTab.java b/src/main/java/com/genyo/mixin/meteor/MixinBetterTab.java index c2fe0c3..4ba255c 100644 --- a/src/main/java/com/genyo/mixin/meteor/MixinBetterTab.java +++ b/src/main/java/com/genyo/mixin/meteor/MixinBetterTab.java @@ -24,7 +24,7 @@ private void injectGetPlayerName(PlayerListEntry playerListEntry, CallbackInfoRe Color enemyColor = Enemies.get().getEnemyColor(); enemyName = playerListEntry.getDisplayName(); - if (enemyName == null) enemyName = Text.literal(playerListEntry.getProfile().getName()); + if (enemyName == null) enemyName = Text.literal(playerListEntry.getProfile().name()); String nameString = enemyName.getString(); diff --git a/src/main/java/com/genyo/mixin/meteor/MixinWWidget.java b/src/main/java/com/genyo/mixin/meteor/MixinWWidget.java new file mode 100644 index 0000000..0a23237 --- /dev/null +++ b/src/main/java/com/genyo/mixin/meteor/MixinWWidget.java @@ -0,0 +1,57 @@ +package com.genyo.mixin.meteor; + +import com.genyo.managers.Managers; +import com.genyo.core.sound.SoundManager; +import com.genyo.systems.config.GenyoConfig; +import meteordevelopment.meteorclient.gui.themes.meteor.widgets.WMeteorModule; +import meteordevelopment.meteorclient.gui.widgets.WWidget; +import net.minecraft.client.gui.Click; +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(value = WWidget.class, remap = false) +public class MixinWWidget { + + @Shadow public boolean mouseOver; + @Unique private boolean genyo_wasOver = false; + + @Inject(method = "mouseMoved", at = @At("TAIL")) + private void onMouseMoved(double mouseX, double mouseY, + double lastMouseX, double lastMouseY, CallbackInfo ci) { + // Only fire on module buttons + if (!(((Object) this) instanceof WMeteorModule)) return; + + if (mouseOver && !genyo_wasOver) { + GenyoConfig cfg = GenyoConfig.get(); + if (cfg != null && cfg.guiSounds.get()) { + float vol = cfg.hoverVolume.get() / 100f; + Managers.SOUND.playUISound(SoundManager.GUI_HOVER, vol, 1f); + } + } + genyo_wasOver = mouseOver; + } + + @Inject(method = "mouseClicked", at = @At("HEAD")) + private void onMouseClicked(Click click, boolean doubled, + CallbackInfoReturnable cir) { + // Only fire on module buttons + if (!(((Object) this) instanceof WMeteorModule)) return; + if (!mouseOver) return; + + GenyoConfig cfg = GenyoConfig.get(); + if (cfg == null || !cfg.guiSounds.get()) return; + + float vol = cfg.clickVolume.get() / 100f; + + if (click.button() == 0) { + Managers.SOUND.playUISound(SoundManager.GUI_CLICK_LEFT, vol, 1f); + } else if (click.button() == 1) { + Managers.SOUND.playUISound(SoundManager.GUI_CLICK_RIGHT, vol, 1f); + } + } +} diff --git a/src/main/java/com/genyo/mixin/network/MixinClientPlayNetworkHandler.java b/src/main/java/com/genyo/mixin/network/MixinClientPlayNetworkHandler.java index dccf5b7..614343e 100644 --- a/src/main/java/com/genyo/mixin/network/MixinClientPlayNetworkHandler.java +++ b/src/main/java/com/genyo/mixin/network/MixinClientPlayNetworkHandler.java @@ -43,7 +43,7 @@ protected MixinClientPlayNetworkHandler(MinecraftClient client, ClientConnection super(client, connection, connectionState); } - @Inject(method = "onExplosion", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkThreadUtils;forceMainThread(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;Lnet/minecraft/util/thread/ThreadExecutor;)V", shift = At.Shift.AFTER)) + @Inject(method = "onExplosion", at = @At("HEAD")) private void onExplosionVelocity(ExplosionS2CPacket packet, CallbackInfo ci) { GenyoVelocity velocity = Modules.get().get(GenyoVelocity.class); if (velocity.explosionConfig.get()) { diff --git a/src/main/java/com/genyo/mixin/network/MixinClientPlayerEntity.java b/src/main/java/com/genyo/mixin/network/MixinClientPlayerEntity.java index 943ac5a..5bd5537 100644 --- a/src/main/java/com/genyo/mixin/network/MixinClientPlayerEntity.java +++ b/src/main/java/com/genyo/mixin/network/MixinClientPlayerEntity.java @@ -4,11 +4,11 @@ import com.genyo.events.entity.SwingEvent; import com.genyo.events.network.*; import com.genyo.events.sync.SyncEvent; -import com.genyo.events.network.*; import com.genyo.imixins.IClientPlayerEntity; import meteordevelopment.meteorclient.MeteorClient; import net.minecraft.client.input.Input; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.Entity; import net.minecraft.util.Hand; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -29,11 +29,6 @@ public abstract class MixinClientPlayerEntity implements IClientPlayerEntity { @Unique private Runnable postAction; - @Shadow - private float lastYaw; - @Shadow - private float lastPitch; - @Shadow protected abstract void sendMovementPackets(); @@ -46,9 +41,6 @@ public abstract class MixinClientPlayerEntity implements IClientPlayerEntity { @Shadow public Input input; - /** - * @param ci - */ @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/" + "minecraft/client/network/AbstractClientPlayerEntity;tick()V", shift = At.Shift.BEFORE, ordinal = 0)) @@ -57,13 +49,9 @@ private void hookTickPre(CallbackInfo ci) MeteorClient.EVENT_BUS.post(new PlayerTickEvent()); } - /** - * @param ci - */ @Inject(method = "sendMovementPackets", at = @At(value = "HEAD"), cancellable = true) private void hookSendMovementPackets(CallbackInfo ci) { - //if (fullNullCheck()) return; - SyncEvent.Pre event = SyncEvent.Pre.get(getYaw(mc.getRenderTickCounter().getTickDelta(true)), getPitch(mc.getRenderTickCounter().getTickDelta(true))); + SyncEvent.Pre event = SyncEvent.Pre.get(getYaw(mc.getRenderTickCounter().getTickProgress(true)), getPitch(mc.getRenderTickCounter().getTickProgress(true))); MeteorClient.EVENT_BUS.post(event); postAction = event.postAction; @@ -80,13 +68,10 @@ private void hookSendMovementPackets(CallbackInfo ci) { @Inject(method = "sendMovementPackets", at = @At("RETURN"), cancellable = true) private void sendMovementPacketsPostHook(CallbackInfo info) { - //if (fullNullCheck()) return; - //mc.player.lastSprinting = pre_sprint_state; - SyncEvent.Post event = SyncEvent.Post.get(); MeteorClient.EVENT_BUS.post(event); - if(postAction != null) { + if (postAction != null) { postAction.run(); postAction = null; } @@ -95,23 +80,13 @@ private void sendMovementPacketsPostHook(CallbackInfo info) { info.cancel(); } - /** - * @param hand - * @param ci - */ @Inject(method = "setCurrentHand", at = @At(value = "HEAD")) private void hookSetCurrentHand(Hand hand, CallbackInfo ci) { MeteorClient.EVENT_BUS.post(SetCurrentHandEvent.get(hand)); } - /** - * @param x - * @param z - * @param ci - */ - @Inject(method = "pushOutOfBlocks", at = @At(value = "HEAD"), - cancellable = true) + @Inject(method = "pushOutOfBlocks", at = @At(value = "HEAD"), cancellable = true) private void onPushOutOfBlocks(double x, double z, CallbackInfo ci) { PushOutOfBlocksEvent pushOutOfBlocksEvent = new PushOutOfBlocksEvent(); @@ -122,19 +97,12 @@ private void onPushOutOfBlocks(double x, double z, CallbackInfo ci) } } - /** - * @param hand - * @param ci - */ @Inject(method = "swingHand", at = @At(value = "RETURN")) private void hookSwingHand(Hand hand, CallbackInfo ci) { MeteorClient.EVENT_BUS.post(SwingEvent.get(hand)); } - /** - * @param ci - */ @Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick()V", shift = At.Shift.AFTER)) private void hookTickMovementPost(CallbackInfo ci) { @@ -144,13 +112,13 @@ private void hookTickMovementPost(CallbackInfo ci) { @Override public float genyo_addon$getLastSpoofedYaw() { - return lastYaw; + return ((Entity) (Object) this).lastYaw; } @Override public float genyo_addon$getLastSpoofedPitch() { - return lastPitch; + return ((Entity) (Object) this).lastPitch; } } diff --git a/src/main/java/com/genyo/mixin/render/MixinRenderTickCounter.java b/src/main/java/com/genyo/mixin/render/MixinRenderTickCounter.java index 885a36a..0eb8b56 100644 --- a/src/main/java/com/genyo/mixin/render/MixinRenderTickCounter.java +++ b/src/main/java/com/genyo/mixin/render/MixinRenderTickCounter.java @@ -14,22 +14,18 @@ public abstract class MixinRenderTickCounter { @Shadow - private float lastFrameDuration; + private float dynamicDeltaTicks; // ← lastFrameDuration @Shadow - private float tickDelta; + private float tickProgress; // ← tickDelta @Shadow - private long prevTimeMillis; + private long lastTimeMillis; // ← prevTimeMillis @Final @Shadow private float tickTime; - /** - * @param timeMillis - * @param cir - */ @Inject(method = "beginRenderTick(J)I", at = @At(value = "HEAD"), cancellable = true) private void hookBeginRenderTick(long timeMillis, CallbackInfoReturnable cir) { @@ -37,11 +33,11 @@ private void hookBeginRenderTick(long timeMillis, CallbackInfoReturnable mc.getRenderTickCounter().getTickDelta(true) + // getTickDelta() -> mc.getRenderTickCounter().getTickProgress(true) /*@EventHandler public void onRender3D(Render3DEvent event) { @@ -137,125 +138,43 @@ public void onRender3D(Render3DEvent event) { @EventHandler public void onRender3D(Render3DEvent event) { - MatrixStack stack = event.matrices; - Camera camera = mc.getEntityRenderDispatcher().camera; - - // --- FILLED QUEUE --- - if (!FILLED_QUEUE.isEmpty() || !FADE_QUEUE.isEmpty() || !FILLED_SIDE_QUEUE.isEmpty()) { - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); - RenderSystem.disableDepthTest(); - setupRender(); - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - - FILLED_QUEUE.forEach(action -> - setFilledBoxVertexes(bufferBuilder, stack.peek().getPositionMatrix(), action.box(), action.color()) - ); - - FADE_QUEUE.forEach(action -> - setFilledFadePoints(action.box(), bufferBuilder, stack.peek().getPositionMatrix(), action.color(), action.color2()) - ); - - FILLED_SIDE_QUEUE.forEach(action -> - setFilledSidePoints(bufferBuilder, stack.peek().getPositionMatrix(), action.box, action.color(), action.side()) - ); - - Render2DEngine.endBuilding(bufferBuilder); - endRender(); - RenderSystem.enableDepthTest(); - - FADE_QUEUE.clear(); - FILLED_SIDE_QUEUE.clear(); - FILLED_QUEUE.clear(); - } - - // --- OUTLINE QUEUE --- - if (!OUTLINE_QUEUE.isEmpty() || !OUTLINE_SIDE_QUEUE.isEmpty()) { - setupRender(); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES); - RenderSystem.disableCull(); - RenderSystem.disableDepthTest(); - RenderSystem.setShader(ShaderProgramKeys.RENDERTYPE_LINES); - RenderSystem.lineWidth(2f); - - OUTLINE_QUEUE.forEach(action -> { - stack.push(); - stack.translate(action.box().minX - camera.getPos().x, action.box().minY - camera.getPos().y, action.box().minZ - camera.getPos().z); - setOutlinePoints(action.box(), stack, buffer, action.color()); - stack.pop(); - }); - - OUTLINE_SIDE_QUEUE.forEach(action -> { - stack.push(); - stack.translate(action.box.minX - camera.getPos().x, action.box.minY - camera.getPos().y, action.box.minZ - camera.getPos().z); - setSideOutlinePoints(action.box, stack, buffer, action.color(), action.side()); - stack.pop(); - }); - - Render2DEngine.endBuilding(buffer); - RenderSystem.enableCull(); - RenderSystem.enableDepthTest(); - endRender(); - OUTLINE_QUEUE.clear(); - OUTLINE_SIDE_QUEUE.clear(); - } - - // --- DEBUG LINE QUEUE --- - if (!DEBUG_LINE_QUEUE.isEmpty()) { - setupRender(); - RenderSystem.disableDepthTest(); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.LINES); - RenderSystem.disableCull(); - RenderSystem.setShader(ShaderProgramKeys.RENDERTYPE_LINES); - - DEBUG_LINE_QUEUE.forEach(action -> { - stack.push(); - stack.translate(action.start.getX() - camera.getPos().x, action.start.getY() - camera.getPos().y, action.start.getZ() - camera.getPos().z); - vertexLine(stack, buffer, 0f, 0f, 0f, - (float)(action.end.getX() - action.start.getX()), - (float)(action.end.getY() - action.start.getY()), - (float)(action.end.getZ() - action.start.getZ()), - action.color); - stack.pop(); - }); - - Render2DEngine.endBuilding(buffer); - RenderSystem.enableCull(); - RenderSystem.enableDepthTest(); - endRender(); - DEBUG_LINE_QUEUE.clear(); - } - - // --- LINE QUEUE --- - if (!LINE_QUEUE.isEmpty()) { - setupRender(); - Tessellator tessellator = Tessellator.getInstance(); - RenderSystem.disableCull(); - RenderSystem.setShader(ShaderProgramKeys.RENDERTYPE_LINES); - RenderSystem.lineWidth(2f); - RenderSystem.disableDepthTest(); - BufferBuilder buffer = tessellator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES); - - LINE_QUEUE.forEach(action -> { - stack.push(); - stack.translate(action.start.getX() - camera.getPos().x, action.start.getY() - camera.getPos().y, action.start.getZ() - camera.getPos().z); - vertexLine(stack, buffer, 0f, 0f, 0f, - (float)(action.end.getX() - action.start.getX()), - (float)(action.end.getY() - action.start.getY()), - (float)(action.end.getZ() - action.start.getZ()), - action.color); - stack.pop(); - }); - - Render2DEngine.endBuilding(buffer); - RenderSystem.enableCull(); - RenderSystem.lineWidth(1f); - RenderSystem.enableDepthTest(); - endRender(); - LINE_QUEUE.clear(); - } + FILLED_QUEUE.forEach(action -> event.renderer.boxSides( + action.box().minX - event.offsetX, action.box().minY - event.offsetY, action.box().minZ - event.offsetZ, + action.box().maxX - event.offsetX, action.box().maxY - event.offsetY, action.box().maxZ - event.offsetZ, + action.color(), 0)); + FILLED_QUEUE.clear(); + + OUTLINE_QUEUE.forEach(action -> event.renderer.boxLines( + action.box().minX - event.offsetX, action.box().minY - event.offsetY, action.box().minZ - event.offsetZ, + action.box().maxX - event.offsetX, action.box().maxY - event.offsetY, action.box().maxZ - event.offsetZ, + action.color(), 0)); + OUTLINE_QUEUE.clear(); + + FILLED_SIDE_QUEUE.forEach(action -> event.renderer.boxSides( + action.box().minX - event.offsetX, action.box().minY - event.offsetY, action.box().minZ - event.offsetZ, + action.box().maxX - event.offsetX, action.box().maxY - event.offsetY, action.box().maxZ - event.offsetZ, + action.color(), 0)); + FILLED_SIDE_QUEUE.clear(); + + OUTLINE_SIDE_QUEUE.forEach(action -> event.renderer.boxLines( + action.box().minX - event.offsetX, action.box().minY - event.offsetY, action.box().minZ - event.offsetZ, + action.box().maxX - event.offsetX, action.box().maxY - event.offsetY, action.box().maxZ - event.offsetZ, + action.color(), 0)); + OUTLINE_SIDE_QUEUE.clear(); + + LINE_QUEUE.forEach(action -> event.renderer.line( + action.start().x - event.offsetX, action.start().y - event.offsetY, action.start().z - event.offsetZ, + action.end().x - event.offsetX, action.end().y - event.offsetY, action.end().z - event.offsetZ, + action.color())); + LINE_QUEUE.clear(); + + DEBUG_LINE_QUEUE.forEach(action -> event.renderer.line( + action.start().x - event.offsetX, action.start().y - event.offsetY, action.start().z - event.offsetZ, + action.end().x - event.offsetX, action.end().y - event.offsetY, action.end().z - event.offsetZ, + action.color())); + DEBUG_LINE_QUEUE.clear(); + + FADE_QUEUE.clear(); } @Deprecated @@ -264,44 +183,7 @@ public static void drawFilledBox(MatrixStack stack, Box box, Color c) { FILLED_QUEUE.add(new FillAction(box, c)); } - public static void setFilledBoxVertexes(@NotNull BufferBuilder bufferBuilder, Matrix4f m, @NotNull Box box, @NotNull Color c) { - float minX = (float) (box.minX - mc.getEntityRenderDispatcher().camera.getPos().getX()); - float minY = (float) (box.minY - mc.getEntityRenderDispatcher().camera.getPos().getY()); - float minZ = (float) (box.minZ - mc.getEntityRenderDispatcher().camera.getPos().getZ()); - float maxX = (float) (box.maxX - mc.getEntityRenderDispatcher().camera.getPos().getX()); - float maxY = (float) (box.maxY - mc.getEntityRenderDispatcher().camera.getPos().getY()); - float maxZ = (float) (box.maxZ - mc.getEntityRenderDispatcher().camera.getPos().getZ()); - - bufferBuilder.vertex(m, minX, minY, minZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, minY, minZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, minY, maxZ).color(c.getPacked()); - bufferBuilder.vertex(m, minX, minY, maxZ).color(c.getPacked()); - - bufferBuilder.vertex(m, minX, minY, minZ).color(c.getPacked()); - bufferBuilder.vertex(m, minX, maxY, minZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, maxY, minZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, minY, minZ).color(c.getPacked()); - - bufferBuilder.vertex(m, maxX, minY, minZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, maxY, minZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, maxY, maxZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, minY, maxZ).color(c.getPacked()); - - bufferBuilder.vertex(m, minX, minY, maxZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, minY, maxZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, maxY, maxZ).color(c.getPacked()); - bufferBuilder.vertex(m, minX, maxY, maxZ).color(c.getPacked()); - - bufferBuilder.vertex(m, minX, minY, minZ).color(c.getPacked()); - bufferBuilder.vertex(m, minX, minY, maxZ).color(c.getPacked()); - bufferBuilder.vertex(m, minX, maxY, maxZ).color(c.getPacked()); - bufferBuilder.vertex(m, minX, maxY, minZ).color(c.getPacked()); - - bufferBuilder.vertex(m, minX, maxY, minZ).color(c.getPacked()); - bufferBuilder.vertex(m, minX, maxY, maxZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, maxY, maxZ).color(c.getPacked()); - bufferBuilder.vertex(m, maxX, maxY, minZ).color(c.getPacked()); - } + public static void setFilledBoxVertexes(@NotNull BufferBuilder bufferBuilder, Matrix4f m, @NotNull Box box, @NotNull Color c) {} public static @NotNull Box interpolateBox(@NotNull Box from, @NotNull Box to, float delta) { double X = Render2DEngine.interpolate(from.maxX, to.maxX, delta); @@ -318,72 +200,20 @@ public static void drawFilledSide(MatrixStack stack, @NotNull Box box, Color c, FILLED_SIDE_QUEUE.add(new FillSideAction(box, c, dir)); } - public static void setFilledSidePoints(BufferBuilder buffer, Matrix4f matrix, Box box, Color c, Direction dir) { - float minX = (float) (box.minX - mc.getEntityRenderDispatcher().camera.getPos().getX()); - float minY = (float) (box.minY - mc.getEntityRenderDispatcher().camera.getPos().getY()); - float minZ = (float) (box.minZ - mc.getEntityRenderDispatcher().camera.getPos().getZ()); - float maxX = (float) (box.maxX - mc.getEntityRenderDispatcher().camera.getPos().getX()); - float maxY = (float) (box.maxY - mc.getEntityRenderDispatcher().camera.getPos().getY()); - float maxZ = (float) (box.maxZ - mc.getEntityRenderDispatcher().camera.getPos().getZ()); - - if (dir == Direction.DOWN) { - buffer.vertex(matrix, minX, minY, minZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, minY, minZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, minY, maxZ).color(c.getPacked()); - buffer.vertex(matrix, minX, minY, maxZ).color(c.getPacked()); - } - - if (dir == Direction.NORTH) { - buffer.vertex(matrix, minX, minY, minZ).color(c.getPacked()); - buffer.vertex(matrix, minX, maxY, minZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, maxY, minZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, minY, minZ).color(c.getPacked()); - } - - if (dir == Direction.EAST) { - buffer.vertex(matrix, maxX, minY, minZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, maxY, minZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, maxY, maxZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, minY, maxZ).color(c.getPacked()); - } - if (dir == Direction.SOUTH) { - buffer.vertex(matrix, minX, minY, maxZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, minY, maxZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, maxY, maxZ).color(c.getPacked()); - buffer.vertex(matrix, minX, maxY, maxZ).color(c.getPacked()); - } - - if (dir == Direction.WEST) { - buffer.vertex(matrix, minX, minY, minZ).color(c.getPacked()); - buffer.vertex(matrix, minX, minY, maxZ).color(c.getPacked()); - buffer.vertex(matrix, minX, maxY, maxZ).color(c.getPacked()); - buffer.vertex(matrix, minX, maxY, minZ).color(c.getPacked()); - } - - if (dir == Direction.UP) { - buffer.vertex(matrix, minX, maxY, minZ).color(c.getPacked()); - buffer.vertex(matrix, minX, maxY, maxZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, maxY, maxZ).color(c.getPacked()); - buffer.vertex(matrix, maxX, maxY, minZ).color(c.getPacked()); - } - } + public static void setFilledSidePoints(BufferBuilder buffer, Matrix4f matrix, Box box, Color c, Direction dir) {} public static void drawTextIn3D(String text, @NotNull Vec3d pos, double offX, double offY, double textOffset, @NotNull Color color) { MatrixStack matrices = new MatrixStack(); Camera camera = mc.gameRenderer.getCamera(); - RenderSystem.disableDepthTest(); - RenderSystem.disableCull(); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch())); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(camera.getYaw() + 180.0F)); - matrices.translate(pos.getX() - camera.getPos().x, pos.getY() - camera.getPos().y, pos.getZ() - camera.getPos().z); + matrices.translate(pos.getX() - camera.getCameraPos().x, pos.getY() - camera.getCameraPos().y, pos.getZ() - camera.getCameraPos().z); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-camera.getYaw())); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch())); setupRender(); matrices.translate(offX, offY - 0.1, -0.01); matrices.scale(-0.025f, -0.025f, 0); //FontRenderers.sf_medium.drawCenteredString(matrices, text, textOffset, 0f, color.getPacked()); - RenderSystem.enableCull(); - RenderSystem.enableDepthTest(); endRender(); } @@ -394,9 +224,9 @@ public static void drawTextIn3D(String text, @NotNull Vec3d pos, double offX, do GL11.glGetIntegerv(GL11.GL_VIEWPORT, viewport); Vector3f target = new Vector3f(); - double deltaX = pos.x - camera.getPos().x; - double deltaY = pos.y - camera.getPos().y; - double deltaZ = pos.z - camera.getPos().z; + double deltaX = pos.x - camera.getCameraPos().x; + double deltaY = pos.y - camera.getCameraPos().y; + double deltaZ = pos.z - camera.getCameraPos().z; Vector4f transformedCoordinates = new Vector4f((float) deltaX, (float) deltaY, (float) deltaZ, 1.f).mul(lastWorldSpaceMatrix); Matrix4f matrixProj = new Matrix4f(lastProjMat); @@ -417,40 +247,7 @@ public static void drawFilledFadeBox(@NotNull MatrixStack stack, @NotNull Box bo FADE_QUEUE.add(new FadeAction(box, c, c1)); } - public static void setFilledFadePoints(Box box, BufferBuilder buffer, Matrix4f posMatrix, Color c, Color c1) { - float minX = (float) (box.minX - mc.getEntityRenderDispatcher().camera.getPos().getX()); - float minY = (float) (box.minY - mc.getEntityRenderDispatcher().camera.getPos().getY()); - float minZ = (float) (box.minZ - mc.getEntityRenderDispatcher().camera.getPos().getZ()); - float maxX = (float) (box.maxX - mc.getEntityRenderDispatcher().camera.getPos().getX()); - float maxY = (float) (box.maxY - mc.getEntityRenderDispatcher().camera.getPos().getY()); - float maxZ = (float) (box.maxZ - mc.getEntityRenderDispatcher().camera.getPos().getZ()); - - - buffer.vertex(posMatrix, minX, minY, minZ).color(c.getPacked()); - buffer.vertex(posMatrix, minX, maxY, minZ).color(c1.getPacked()); - buffer.vertex(posMatrix, maxX, maxY, minZ).color(c1.getPacked()); - buffer.vertex(posMatrix, maxX, minY, minZ).color(c.getPacked()); - - buffer.vertex(posMatrix, maxX, minY, minZ).color(c.getPacked()); - buffer.vertex(posMatrix, maxX, maxY, minZ).color(c1.getPacked()); - buffer.vertex(posMatrix, maxX, maxY, maxZ).color(c1.getPacked()); - buffer.vertex(posMatrix, maxX, minY, maxZ).color(c.getPacked()); - - buffer.vertex(posMatrix, minX, minY, maxZ).color(c.getPacked()); - buffer.vertex(posMatrix, maxX, minY, maxZ).color(c.getPacked()); - buffer.vertex(posMatrix, maxX, maxY, maxZ).color(c1.getPacked()); - buffer.vertex(posMatrix, minX, maxY, maxZ).color(c1.getPacked()); - - buffer.vertex(posMatrix, minX, minY, minZ).color(c.getPacked()); - buffer.vertex(posMatrix, minX, minY, maxZ).color(c.getPacked()); - buffer.vertex(posMatrix, minX, maxY, maxZ).color(c1.getPacked()); - buffer.vertex(posMatrix, minX, maxY, minZ).color(c1.getPacked()); - - buffer.vertex(posMatrix, minX, maxY, minZ).color(c1.getPacked()); - buffer.vertex(posMatrix, minX, maxY, maxZ).color(c1.getPacked()); - buffer.vertex(posMatrix, maxX, maxY, maxZ).color(c1.getPacked()); - buffer.vertex(posMatrix, maxX, maxY, minZ).color(c1.getPacked()); - } + public static void setFilledFadePoints(Box box, BufferBuilder buffer, Matrix4f posMatrix, Color c, Color c1) {} public static void drawLine(@NotNull Vec3d start, @NotNull Vec3d end, @NotNull Color color) { LINE_QUEUE.add(new LineAction(start, end, color)); @@ -461,126 +258,18 @@ public static void drawBoxOutline(@NotNull Box box, Color color, float lineWidth OUTLINE_QUEUE.add(new OutlineAction(box, color, lineWidth)); } - public static void setOutlinePoints(Box box, MatrixStack matrices, BufferBuilder buffer, Color color) { - box = box.offset(new Vec3d(box.minX, box.minY, box.minZ).negate()); - - float x1 = (float) box.minX; - float y1 = (float) box.minY; - float z1 = (float) box.minZ; - float x2 = (float) box.maxX; - float y2 = (float) box.maxY; - float z2 = (float) box.maxZ; - - vertexLine(matrices, buffer, x1, y1, z1, x2, y1, z1, color); - vertexLine(matrices, buffer, x2, y1, z1, x2, y1, z2, color); - vertexLine(matrices, buffer, x2, y1, z2, x1, y1, z2, color); - vertexLine(matrices, buffer, x1, y1, z2, x1, y1, z1, color); - vertexLine(matrices, buffer, x1, y1, z2, x1, y2, z2, color); - vertexLine(matrices, buffer, x1, y1, z1, x1, y2, z1, color); - vertexLine(matrices, buffer, x2, y1, z2, x2, y2, z2, color); - vertexLine(matrices, buffer, x2, y1, z1, x2, y2, z1, color); - vertexLine(matrices, buffer, x1, y2, z1, x2, y2, z1, color); - vertexLine(matrices, buffer, x2, y2, z1, x2, y2, z2, color); - vertexLine(matrices, buffer, x2, y2, z2, x1, y2, z2, color); - vertexLine(matrices, buffer, x1, y2, z2, x1, y2, z1, color); - } + public static void setOutlinePoints(Box box, MatrixStack matrices, BufferBuilder buffer, Color color) {} @Deprecated public static void drawSideOutline(@NotNull Box box, Color color, float lineWidth, Direction dir) { OUTLINE_SIDE_QUEUE.add(new OutlineSideAction(box, color, lineWidth, dir)); } - public static void setSideOutlinePoints(Box box, MatrixStack matrices, BufferBuilder buffer, Color color, Direction dir) { - box = box.offset(new Vec3d(box.minX, box.minY, box.minZ).negate()); - - float x1 = (float) box.minX; - float y1 = (float) box.minY; - float z1 = (float) box.minZ; - float x2 = (float) box.maxX; - float y2 = (float) box.maxY; - float z2 = (float) box.maxZ; - - switch (dir) { - case UP -> { - vertexLine(matrices, buffer, x1, y2, z1, x2, y2, z1, color); - vertexLine(matrices, buffer, x2, y2, z1, x2, y2, z2, color); - vertexLine(matrices, buffer, x2, y2, z2, x1, y2, z2, color); - vertexLine(matrices, buffer, x1, y2, z2, x1, y2, z1, color); - } - case DOWN -> { - vertexLine(matrices, buffer, x1, y1, z1, x2, y1, z1, color); - vertexLine(matrices, buffer, x2, y1, z1, x2, y1, z2, color); - vertexLine(matrices, buffer, x2, y1, z2, x1, y1, z2, color); - vertexLine(matrices, buffer, x1, y1, z2, x1, y1, z1, color); - } - case EAST -> { - vertexLine(matrices, buffer, x2, y1, z1, x2, y2, z1, color); - vertexLine(matrices, buffer, x2, y1, z2, x2, y2, z2, color); - vertexLine(matrices, buffer, x2, y2, z2, x2, y2, z1, color); - vertexLine(matrices, buffer, x2, y1, z2, x2, y1, z1, color); - } - case WEST -> { - vertexLine(matrices, buffer, x1, y1, z1, x1, y2, z1, color); - vertexLine(matrices, buffer, x1, y1, z2, x1, y2, z2, color); - vertexLine(matrices, buffer, x1, y2, z2, x1, y2, z1, color); - vertexLine(matrices, buffer, x1, y1, z2, x1, y1, z1, color); - } - case NORTH -> { - vertexLine(matrices, buffer, x2, y1, z1, x2, y2, z1, color); - vertexLine(matrices, buffer, x1, y1, z1, x1, y2, z1, color); - vertexLine(matrices, buffer, x2, y1, z1, x1, y1, z1, color); - vertexLine(matrices, buffer, x2, y2, z1, x1, y2, z1, color); - } - case SOUTH -> { - vertexLine(matrices, buffer, x1, y1, z2, x1, y2, z2, color); - vertexLine(matrices, buffer, x2, y1, z2, x2, y2, z2, color); - vertexLine(matrices, buffer, x1, y1, z2, x2, y1, z2, color); - vertexLine(matrices, buffer, x1, y2, z2, x2, y2, z2, color); - } - } - } + public static void setSideOutlinePoints(Box box, MatrixStack matrices, BufferBuilder buffer, Color color, Direction dir) {} - public static void drawHoleOutline(@NotNull Box box, Color color, float lineWidth) { - setupRender(); - MatrixStack matrices = matrixFrom(box.minX, box.minY, box.minZ); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES); - - RenderSystem.disableCull(); - RenderSystem.setShader(ShaderProgramKeys.RENDERTYPE_LINES); - RenderSystem.lineWidth(lineWidth); - - box = box.offset(new Vec3d(box.minX, box.minY, box.minZ).negate()); - - float x1 = (float) box.minX; - float y1 = (float) box.minY; - float y2 = (float) box.maxY; - float z1 = (float) box.minZ; - float x2 = (float) box.maxX; - float z2 = (float) box.maxZ; - - vertexLine(matrices, buffer, x1, y1, z1, x2, y1, z1, color); - vertexLine(matrices, buffer, x2, y1, z1, x2, y1, z2, color); - vertexLine(matrices, buffer, x2, y1, z2, x1, y1, z2, color); - vertexLine(matrices, buffer, x1, y1, z2, x1, y1, z1, color); - - vertexLine(matrices, buffer, x1, y1, z1, x1, y2, z1, color); - vertexLine(matrices, buffer, x2, y1, z2, x2, y2, z2, color); - vertexLine(matrices, buffer, x1, y1, z2, x1, y2, z2, color); - vertexLine(matrices, buffer, x2, y1, z1, x2, y2, z1, color); - - Render2DEngine.endBuilding(buffer); - RenderSystem.enableCull(); - endRender(); - } + public static void drawHoleOutline(@NotNull Box box, Color color, float lineWidth) {} - public static void vertexLine(@NotNull MatrixStack matrices, @NotNull VertexConsumer buffer, float x1, float y1, float z1, float x2, float y2, float z2, @NotNull Color lineColor) { - Matrix4f model = matrices.peek().getPositionMatrix(); - MatrixStack.Entry entry = matrices.peek(); - Vector3f normalVec = getNormal(x1, y1, z1, x2, y2, z2); - buffer.vertex(model, x1, y1, z1).color(lineColor.r, lineColor.g, lineColor.b, lineColor.a).normal(entry, normalVec.x(), normalVec.y(), normalVec.z()); - buffer.vertex(model, x2, y2, z2).color(lineColor.r, lineColor.g, lineColor.b, lineColor.a).normal(entry, normalVec.x(), normalVec.y(), normalVec.z()); - } + public static void vertexLine(@NotNull MatrixStack matrices, @NotNull VertexConsumer buffer, float x1, float y1, float z1, float x2, float y2, float z2, @NotNull Color lineColor) {} public static @NotNull Vector3f getNormal(float x1, float y1, float z1, float x2, float y2, float z2) { float xNormal = x2 - x1; @@ -595,7 +284,7 @@ public static void vertexLine(@NotNull MatrixStack matrices, @NotNull VertexCons MatrixStack matrices = new MatrixStack(); Camera camera = MinecraftClient.getInstance().gameRenderer.getCamera(); - matrices.translate(x - camera.getPos().x, y - camera.getPos().y, z - camera.getPos().z); + matrices.translate(x - camera.getCameraPos().x, y - camera.getCameraPos().y, z - camera.getCameraPos().z); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-camera.getYaw())); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch())); @@ -603,299 +292,30 @@ public static void vertexLine(@NotNull MatrixStack matrices, @NotNull VertexCons } public static void setupRender() { - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); } public static void endRender() { - RenderSystem.disableBlend(); + GL11.glDisable(GL11.GL_BLEND); } - public static void drawTargetEsp(MatrixStack stack, @NotNull Entity target) { - ArrayList vecs = new ArrayList<>(); - ArrayList vecs1 = new ArrayList<>(); - ArrayList vecs2 = new ArrayList<>(); - - double x = target.prevX + (target.getX() - target.prevX) * getTickDelta() - - mc.getEntityRenderDispatcher().camera.getPos().getX(); - double y = target.prevY + (target.getY() - target.prevY) * getTickDelta() - - mc.getEntityRenderDispatcher().camera.getPos().getY(); - double z = target.prevZ + (target.getZ() - target.prevZ) * getTickDelta() - - mc.getEntityRenderDispatcher().camera.getPos().getZ(); - - - double height = target.getHeight(); - - for (int i = 0; i <= 361; ++i) { - double v = Math.sin(Math.toRadians(i)); - double u = Math.cos(Math.toRadians(i)); - Vec3d vec = new Vec3d((float) (u * 0.5f), height, (float) (v * 0.5f)); - vecs.add(vec); - - double v1 = Math.sin(Math.toRadians((i + 120) % 360)); - double u1 = Math.cos(Math.toRadians(i + 120) % 360); - Vec3d vec1 = new Vec3d((float) (u1 * 0.5f), height, (float) (v1 * 0.5f)); - vecs1.add(vec1); - - double v2 = Math.sin(Math.toRadians((i + 240) % 360)); - double u2 = Math.cos(Math.toRadians((i + 240) % 360)); - Vec3d vec2 = new Vec3d((float) (u2 * 0.5f), height, (float) (v2 * 0.5f)); - vecs2.add(vec2); - height -= 0.004f; - } + public static void drawTargetEsp(MatrixStack stack, @NotNull Entity target) {} + public static void renderCrosses(@NotNull Box box, Color color, float lineWidth) {} - stack.push(); - stack.translate(x, y, z); - BufferBuilder bufferBuilder; - setupRender(); - RenderSystem.disableCull(); - RenderSystem.disableDepthTest(); + public static void drawSphere(MatrixStack matrix, float radius, int slices, int stacks, int color) {} - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - bufferBuilder = Tessellator.getInstance().begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); + public static void drawCylinder(MatrixStack stack, final float radius, final float height, final int slices, final int stacks, int color) {} - Matrix4f matrix = stack.peek().getPositionMatrix(); - for (int j = 0; j < vecs.size() - 1; ++j) { - float alpha = 1f - (((float) j + ((System.currentTimeMillis() - System.currentTimeMillis()) / 5f)) % 360) / 60f; - bufferBuilder.vertex(matrix, (float) vecs.get(j).x, (float) vecs.get(j).y, (float) vecs.get(j).z).color(Hud.get().textColors.get().getFirst().a((int) (alpha * 255)).getPacked()); - bufferBuilder.vertex(matrix, (float) vecs.get(j + 1).x, (float) vecs.get(j + 1).y + 0.1f, (float) vecs.get(j + 1).z).color(Hud.get().textColors.get().getFirst().a((int) (alpha * 255f)).getPacked()); - } - Render2DEngine.endBuilding(bufferBuilder); - - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - bufferBuilder = Tessellator.getInstance().begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); - for (int j = 0; j < vecs1.size() - 1; ++j) { - float alpha = 1f - (((float) j + ((System.currentTimeMillis() - System.currentTimeMillis()) / 5f)) % 360) / 60f; - bufferBuilder.vertex(matrix, (float) vecs1.get(j).x, (float) vecs1.get(j).y, (float) vecs1.get(j).z).color(Hud.get().textColors.get().getFirst().a((int) (alpha * 255)).getPacked()); - bufferBuilder.vertex(matrix, (float) vecs1.get(j + 1).x, (float) vecs1.get(j + 1).y + 0.1f, (float) vecs1.get(j + 1).z).color(Hud.get().textColors.get().getFirst().a((int) (alpha * 255f)).getPacked()); - } - Render2DEngine.endBuilding(bufferBuilder); - - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - bufferBuilder = Tessellator.getInstance().begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); - for (int j = 0; j < vecs2.size() - 1; ++j) { - float alpha = 1f - (((float) j + ((System.currentTimeMillis() - System.currentTimeMillis()) / 5f)) % 360) / 60f; - bufferBuilder.vertex(matrix, (float) vecs2.get(j).x, (float) vecs2.get(j).y, (float) vecs2.get(j).z).color(Hud.get().textColors.get().getFirst().a((int) (alpha * 255)).getPacked()); - bufferBuilder.vertex(matrix, (float) vecs2.get(j + 1).x, (float) vecs2.get(j + 1).y + 0.1f, (float) vecs2.get(j + 1).z).color(Hud.get().textColors.get().getFirst().a((int) (alpha * 255f)).getPacked()); - } - Render2DEngine.endBuilding(bufferBuilder); - - RenderSystem.enableCull(); - stack.translate(-x, -y, -z); - endRender(); - RenderSystem.enableDepthTest(); - stack.pop(); - } + public static void drawCircle3D(MatrixStack stack, Entity ent, float radius, int color, int points, boolean hudColor, int colorOffset) {} - public static void renderCrosses(@NotNull Box box, Color color, float lineWidth) { - setupRender(); - MatrixStack matrices = matrixFrom(box.minX, box.minY, box.minZ); - RenderSystem.disableCull(); - RenderSystem.setShader(ShaderProgramKeys.RENDERTYPE_LINES); - RenderSystem.lineWidth(lineWidth); - BufferBuilder buffer = Tessellator.getInstance().begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES); - - box = box.offset(new Vec3d(box.minX, box.minY, box.minZ).negate()); - - vertexLine(matrices, buffer, (float) box.maxX, (float) box.minY, (float) box.minZ, (float) box.minX, (float) box.minY, (float) box.maxZ, color); - vertexLine(matrices, buffer, (float) box.minX, (float) box.minY, (float) box.minZ, (float) box.maxX, (float) box.minY, (float) box.maxZ, color); - - Render2DEngine.endBuilding(buffer); - RenderSystem.enableCull(); - endRender(); - } - - public static void drawSphere(MatrixStack matrix, float radius, int slices, int stacks, int color) { - float drho = 3.1415927F / ((float) stacks); - float dtheta = 6.2831855F / ((float) slices - 1f); - float rho; - float theta; - float x; - float y; - float z; - int i; - int j; - setupRender(); - for (i = 1; i < stacks; ++i) { - rho = (float) i * drho; - - BufferBuilder buffer = Tessellator.getInstance().begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP, VertexFormats.POSITION_COLOR); - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - - for (j = 0; j < slices; ++j) { - theta = (float) j * dtheta; - x = (float) (Math.cos(theta) * Math.sin(rho)); - y = (float) (Math.sin(theta) * Math.sin(rho)); - z = (float) Math.cos(rho); - buffer.vertex(matrix.peek().getPositionMatrix(), x * radius, y * radius, z * radius).color(color); - } - Render2DEngine.endBuilding(buffer); - } - - for (j = 0; j < slices; ++j) { - theta = (float) j * dtheta; - - BufferBuilder buffer = Tessellator.getInstance().begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP, VertexFormats.POSITION_COLOR); - - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - - for (i = 0; i <= stacks; ++i) { - rho = (float) i * drho; - x = (float) (Math.cos(theta) * Math.sin(rho)); - y = (float) (Math.sin(theta) * Math.sin(rho)); - z = (float) Math.cos(rho); - buffer.vertex(matrix.peek().getPositionMatrix(), x * radius, y * radius, z * radius).color(color); - } - BufferRenderer.drawWithGlobalProgram(buffer.end()); - } - endRender(); - } - - public static void drawCylinder(MatrixStack stack, final float radius, final float height, final int slices, final int stacks, int color) { - - final float da = (float) ((Math.PI * 2f) / slices); - final float dz = height / stacks; - - BufferBuilder buffer = Tessellator.getInstance().begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP, VertexFormats.POSITION_COLOR); - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - - float y = 0; - - for (int j = 0; j <= stacks; ++j) { - for (int i = 0; i <= slices; ++i) { - final float x = (float) Math.cos(i * da); - final float z = (float) Math.sin(i * da); - buffer.vertex(stack.peek().getPositionMatrix(), x * radius, y, z * radius).color(color); - } - y += dz; - } - - BufferRenderer.drawWithGlobalProgram(buffer.end()); - - buffer = Tessellator.getInstance().begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP, VertexFormats.POSITION_COLOR); - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - - for (int i = 0; i <= slices; ++i) { - final float x = (float) Math.cos(i * da); - final float z = (float) Math.sin(i * da); - - buffer.vertex(stack.peek().getPositionMatrix(), x * radius, 0, z * radius).color(color); - buffer.vertex(stack.peek().getPositionMatrix(), x * radius, height, z * radius).color(color); - } - - BufferRenderer.drawWithGlobalProgram(buffer.end()); - } - - - public static void drawCircle3D(MatrixStack stack, Entity ent, float radius, int color, int points, boolean hudColor, int colorOffset) { - setupRender(); - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - BufferBuilder bufferBuilder = Tessellator.getInstance().begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP, VertexFormats.POSITION_COLOR); - double x = ent.prevX + (ent.getX() - ent.prevX) * getTickDelta() - mc.getEntityRenderDispatcher().camera.getPos().getX(); - double y = ent.prevY + (ent.getY() - ent.prevY) * getTickDelta() - mc.getEntityRenderDispatcher().camera.getPos().getY(); - double z = ent.prevZ + (ent.getZ() - ent.prevZ) * getTickDelta() - mc.getEntityRenderDispatcher().camera.getPos().getZ(); - stack.push(); - stack.translate(x, y, z); - - Matrix4f matrix = stack.peek().getPositionMatrix(); - for (int i = 0; i <= points; i++) { - if (hudColor) - color = Hud.get().textColors.get().getFirst().getPacked(); - - bufferBuilder.vertex(matrix, (float) (radius * Math.cos(i * 6.28 / points)), 0f, (float) (radius * Math.sin(i * 6.28 / points))).color(color); - } - - BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); - endRender(); - stack.translate(-x, -y, -z); - stack.pop(); - } - - public static void drawOldTargetEsp(MatrixStack stack, Entity target) { - double cs = prevCircleStep + (circleStep - prevCircleStep) * getTickDelta(); - double prevSinAnim = absSinAnimation(cs - 0.45f); - double sinAnim = absSinAnimation(cs); - double x = target.prevX + (target.getX() - target.prevX) * getTickDelta() - mc.getEntityRenderDispatcher().camera.getPos().getX(); - double y = target.prevY + (target.getY() - target.prevY) * getTickDelta() - mc.getEntityRenderDispatcher().camera.getPos().getY() + prevSinAnim * target.getHeight(); - double z = target.prevZ + (target.getZ() - target.prevZ) * getTickDelta() - mc.getEntityRenderDispatcher().camera.getPos().getZ(); - double nextY = target.prevY + (target.getY() - target.prevY) * getTickDelta() - mc.getEntityRenderDispatcher().camera.getPos().getY() + sinAnim * target.getHeight(); - stack.push(); - setupRender(); - RenderSystem.disableCull(); - RenderSystem.disableDepthTest(); - BufferBuilder bufferBuilder = Tessellator.getInstance().begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); - - RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); - float cos; - float sin; - for (int i = 0; i <= 30; i++) { - cos = (float) (x + Math.cos(i * 6.28 / 30) * target.getWidth() * 0.8); - sin = (float) (z + Math.sin(i * 6.28 / 30) * target.getWidth() * 0.8); - bufferBuilder.vertex(stack.peek().getPositionMatrix(), cos, (float) nextY, sin).color(Hud.get().textColors.get().getFirst().a(170).getPacked()); - bufferBuilder.vertex(stack.peek().getPositionMatrix(), cos, (float) y, sin).color(Hud.get().textColors.get().getFirst().a(0).getPacked()); - } - Render2DEngine.endBuilding(bufferBuilder); - RenderSystem.enableCull(); - endRender(); - RenderSystem.enableDepthTest(); - stack.pop(); - } + public static void drawOldTargetEsp(MatrixStack stack, Entity target) {} // Kalry не пасть // anti yg protection - public static void renderGhosts(int espLength, int factor, float shaking, float amplitude, Entity target) { - Camera camera = mc.gameRenderer.getCamera(); - - double tPosX = Render2DEngine.interpolate(target.prevX, target.getX(), Render3DEngine.getTickDelta()) - camera.getPos().x; - double tPosY = Render2DEngine.interpolate(target.prevY, target.getY(), Render3DEngine.getTickDelta()) - camera.getPos().y; - double tPosZ = Render2DEngine.interpolate(target.prevZ, target.getZ(), Render3DEngine.getTickDelta()) - camera.getPos().z; - float iAge = (float) Render2DEngine.interpolate(target.age - 1, target.age, Render3DEngine.getTickDelta()); - - RenderSystem.enableBlend(); - RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE); - RenderSystem.setShader(ShaderProgramKeys.POSITION_TEX_COLOR); - BufferBuilder buffer = Tessellator.getInstance().begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR); - - boolean canSee = mc.player.canSee(target); - - if (canSee) { - RenderSystem.enableDepthTest(); - RenderSystem.depthMask(false); - } else RenderSystem.disableDepthTest(); - - for (int j = 0; j < 3; j++) { - for (int i = 0; i <= espLength; i++) { - double radians = Math.toRadians((((float) i / 1.5f + iAge) * factor + (j * 120)) % (factor * 360)); - double sinQuad = Math.sin(Math.toRadians(iAge * 2.5f + i * (j + 1)) * amplitude) / shaking; - - float offset = ((float) i / espLength); - MatrixStack matrices = new MatrixStack(); - matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch())); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(camera.getYaw() + 180.0F)); - matrices.translate(tPosX + Math.cos(radians) * target.getWidth(), (tPosY + 1 + sinQuad), tPosZ + Math.sin(radians) * target.getWidth()); - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-camera.getYaw())); - matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch())); - Matrix4f matrix = matrices.peek().getPositionMatrix(); - int color = Hud.get().textColors.get().getFirst().getPacked(); - float scale = Math.max(0.24f * (offset), 0.2f); - buffer.vertex(matrix, -scale, scale, 0).texture(0f, 1f).color(color); - buffer.vertex(matrix, scale, scale, 0).texture(1f, 1f).color(color); - buffer.vertex(matrix, scale, -scale, 0).texture(1f, 0).color(color); - buffer.vertex(matrix, -scale, -scale, 0).texture(0, 0).color(color); - } - } - - BufferRenderer.drawWithGlobalProgram(buffer.end()); - - if (canSee) { - RenderSystem.depthMask(true); - RenderSystem.disableDepthTest(); - } else RenderSystem.enableDepthTest(); - - RenderSystem.disableBlend(); - } + public static void renderGhosts(int espLength, int factor, float shaking, float amplitude, Entity target) {} public static void updateTargetESP() { prevCircleStep = circleStep; @@ -907,9 +327,9 @@ public static double absSinAnimation(double input) { } public static Vec3d interpolatePos(float prevposX, float prevposY, float prevposZ, float posX, float posY, float posZ) { - double x = prevposX + ((posX - prevposX) * getTickDelta()) - mc.getEntityRenderDispatcher().camera.getPos().getX(); - double y = prevposY + ((posY - prevposY) * getTickDelta()) - mc.getEntityRenderDispatcher().camera.getPos().getY(); - double z = prevposZ + ((posZ - prevposZ) * getTickDelta()) - mc.getEntityRenderDispatcher().camera.getPos().getZ(); + double x = prevposX + ((posX - prevposX) * getTickDelta()) - mc.getEntityRenderDispatcher().camera.getCameraPos().getX(); + double y = prevposY + ((posY - prevposY) * getTickDelta()) - mc.getEntityRenderDispatcher().camera.getCameraPos().getY(); + double z = prevposZ + ((posZ - prevposZ) * getTickDelta()) - mc.getEntityRenderDispatcher().camera.getCameraPos().getZ(); return new Vec3d(x, y, z); } @@ -918,7 +338,7 @@ public static void drawLineDebug(Vec3d start, Vec3d end, Color color) { } public static float getTickDelta() { - return mc.getRenderTickCounter().getTickDelta(true); + return mc.getRenderTickCounter().getTickProgress(true); } public record FillAction(Box box, Color color) { diff --git a/src/main/java/com/genyo/systems/config/GenyoConfig.java b/src/main/java/com/genyo/systems/config/GenyoConfig.java index 2c66316..7ccd1bc 100644 --- a/src/main/java/com/genyo/systems/config/GenyoConfig.java +++ b/src/main/java/com/genyo/systems/config/GenyoConfig.java @@ -33,6 +33,33 @@ public class GenyoConfig extends System { .build() ); + // In sgSounds group, add these three: + + public final Setting guiSounds = sgSounds.add(new BoolSetting.Builder() + .name("gui-sounds") + .description("Play sounds when hovering and clicking in Meteor's GUI.") + .defaultValue(true) + .build() + ); + + public final Setting hoverVolume = sgSounds.add(new IntSetting.Builder() + .name("hover-volume") + .description("Volume of the hover sound.") + .min(1).defaultValue(60).max(100) + .sliderRange(1, 100) + .visible(guiSounds::get) + .build() + ); + + public final Setting clickVolume = sgSounds.add(new IntSetting.Builder() + .name("click-volume") + .description("Volume of left/right click sounds.") + .min(1).defaultValue(80).max(100) + .sliderRange(1, 100) + .visible(guiSounds::get) + .build() + ); + public final Setting blackPerson = sgSounds.add(new BoolSetting.Builder() .name("black-person") .description("Detect when black person") @@ -85,7 +112,7 @@ public NbtCompound toTag() { @Override public GenyoConfig fromTag(NbtCompound tag) { - if (tag.contains("settings")) settings.fromTag(tag.getCompound("settings")); + if (tag.contains("settings")) tag.getCompound("settings").ifPresent(settings::fromTag); return this; } diff --git a/src/main/java/com/genyo/systems/enemies/Enemies.java b/src/main/java/com/genyo/systems/enemies/Enemies.java index 0b09117..c5f0e22 100644 --- a/src/main/java/com/genyo/systems/enemies/Enemies.java +++ b/src/main/java/com/genyo/systems/enemies/Enemies.java @@ -125,7 +125,7 @@ public Enemy get(PlayerEntity player) { } public Enemy get(PlayerListEntry player) { - return get(player.getProfile().getName()); + return get(player.getProfile().name()); } public boolean isEnemy(PlayerEntity player) { @@ -170,16 +170,16 @@ public NbtCompound toTag() { @Override public Enemies fromTag(NbtCompound tag) { enemies.clear(); - if (tag.contains("settings")) settings.fromTag(tag.getCompound("settings")); + if (tag.contains("settings")) tag.getCompound("settings").ifPresent(settings::fromTag); - for (NbtElement itemTag : tag.getList("enemies", 10)) { + for (NbtElement itemTag : tag.getList("enemies").orElse(new net.minecraft.nbt.NbtList())) { NbtCompound enemyTag = (NbtCompound) itemTag; if (!enemyTag.contains("name")) continue; - String name = enemyTag.getString("name"); + String name = enemyTag.getString("name").orElse(""); if (get(name) != null) continue; - String uuid = enemyTag.getString("id"); + String uuid = enemyTag.getString("id").orElse(""); Enemy enemy = !uuid.isBlank() ? new Enemy(name, UndashedUuid.fromStringLenient(uuid)) : new Enemy(name); diff --git a/src/main/java/com/genyo/systems/enemies/Enemy.java b/src/main/java/com/genyo/systems/enemies/Enemy.java index 16ebedc..5c5d22a 100644 --- a/src/main/java/com/genyo/systems/enemies/Enemy.java +++ b/src/main/java/com/genyo/systems/enemies/Enemy.java @@ -8,8 +8,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; import java.util.Objects; import java.util.UUID; @@ -19,7 +18,7 @@ public class Enemy implements ISerializable, Comparable { public volatile String name; private volatile @Nullable UUID id; - private volatile @Nullable PlayerHeadTexture headTexture; + private volatile byte[] headTexture; private volatile boolean updating; public Enemy(String name, @Nullable UUID id) { @@ -45,7 +44,7 @@ public String getName() { } public PlayerHeadTexture getHead() { - return headTexture != null ? headTexture : PlayerHeadUtils.STEVE_HEAD; + return headTexture != null ? new PlayerHeadTexture(headTexture, false) : PlayerHeadUtils.STEVE_HEAD; } public void updateInfo() { diff --git a/src/main/java/com/genyo/systems/hud/GenyoTargetHud.java b/src/main/java/com/genyo/systems/hud/GenyoTargetHud.java new file mode 100644 index 0000000..57b743c --- /dev/null +++ b/src/main/java/com/genyo/systems/hud/GenyoTargetHud.java @@ -0,0 +1,582 @@ +package com.genyo.systems.hud; + +import com.genyo.Genyo; +import com.genyo.systems.modules.combat.GenyoAutoCrystal; +import com.genyo.managers.Managers; +import com.genyo.systems.modules.combat.KFCSpawnKill; +import meteordevelopment.meteorclient.settings.*; +import meteordevelopment.meteorclient.systems.hud.*; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.utils.render.color.Color; +import meteordevelopment.meteorclient.utils.render.color.SettingColor; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.ProfileComponent; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.math.MathHelper; + +import java.util.ArrayList; +import java.util.List; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class GenyoTargetHud extends HudElement { + + public static final HudElementInfo INFO = new HudElementInfo<>( + Genyo.HUD_GROUP, "target-hud", "Displays info about your crystal/killaura target.", GenyoTargetHud::new + ); + + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final SettingGroup sgColors = settings.createGroup("Colors"); + private final SettingGroup sgScale = settings.createGroup("Scale"); + + // --- General --- + private final Setting showFace = sgGeneral.add(new BoolSetting.Builder() + .name("show-face") + .description("Shows the target's player face on the left side of the HUD.") + .defaultValue(true) + .build() + ); + + private final Setting flatFace = sgGeneral.add(new BoolSetting.Builder() + .name("flat-face") + .description("Renders a flat 2D face instead of the 3D player head.") + .defaultValue(false) + .visible(showFace::get) + .build() + ); + + private final Setting showHealth = sgGeneral.add(new BoolSetting.Builder() + .name("show-health") + .description("Shows target health and absorption.") + .defaultValue(true) + .build() + ); + + private final Setting showArmor = sgGeneral.add(new BoolSetting.Builder() + .name("show-armor") + .description("Shows target armor durability bars.") + .defaultValue(true) + .build() + ); + + private final Setting showArmorItems = sgGeneral.add(new BoolSetting.Builder() + .name("show-armor-items") + .description("Renders armor item icons above bars.") + .defaultValue(true) + .build() + ); + + private final Setting showGearPercent = sgGeneral.add(new BoolSetting.Builder() + .name("show-gear-percent") + .description("Shows armor durability percentage(s).") + .defaultValue(true) + .build() + ); + + private final Setting perPieceGear = sgGeneral.add(new BoolSetting.Builder() + .name("per-piece-gear") + .description("Show each piece's durability % above its icon instead of an average.") + .defaultValue(false) + .visible(showGearPercent::get) + .build() + ); + + private final Setting showHands = sgGeneral.add(new BoolSetting.Builder() + .name("show-hands") + .description("Renders main hand and offhand items on the right.") + .defaultValue(true) + .build() + ); + + private final Setting showDistance = sgGeneral.add(new BoolSetting.Builder() + .name("show-distance") + .description("Shows distance to target.") + .defaultValue(true) + .build() + ); + + private final Setting showPing = sgGeneral.add(new BoolSetting.Builder() + .name("show-ping") + .description("Shows target ping.") + .defaultValue(true) + .build() + ); + + private final Setting showSource = sgGeneral.add(new BoolSetting.Builder() + .name("show-source") + .description("Shows [AC] or [KA] source tag.") + .defaultValue(true) + .build() + ); + + private final Setting showPops = sgGeneral.add(new BoolSetting.Builder() + .name("show-pops") + .description("Shows totem pop counter next to the target name.") + .defaultValue(true) + .build() + ); + + private final Setting shadow = sgGeneral.add(new BoolSetting.Builder() + .name("shadow") + .description("Renders shadow behind text.") + .defaultValue(true) + .build() + ); + + // --- Colors --- + private final Setting bgColor = sgColors.add(new ColorSetting.Builder() + .name("background-color") + .defaultValue(new SettingColor(0, 0, 0, 120)) + .build() + ); + + private final Setting borderColor = sgColors.add(new ColorSetting.Builder() + .name("border-color") + .defaultValue(new SettingColor(80, 80, 80, 180)) + .build() + ); + + private final Setting nameColor = sgColors.add(new ColorSetting.Builder() + .name("name-color") + .defaultValue(new SettingColor(255, 255, 255, 255)) + .build() + ); + + private final Setting healthColorHigh = sgColors.add(new ColorSetting.Builder() + .name("health-color-high") + .defaultValue(new SettingColor(80, 220, 80, 255)) + .build() + ); + + private final Setting healthColorLow = sgColors.add(new ColorSetting.Builder() + .name("health-color-low") + .defaultValue(new SettingColor(220, 60, 60, 255)) + .build() + ); + + private final Setting armorColor = sgColors.add(new ColorSetting.Builder() + .name("armor-color") + .defaultValue(new SettingColor(100, 180, 255, 255)) + .build() + ); + + private final Setting textColor = sgColors.add(new ColorSetting.Builder() + .name("text-color") + .defaultValue(new SettingColor(200, 200, 200, 255)) + .build() + ); + + private final Setting popColor = sgColors.add(new ColorSetting.Builder() + .name("pop-color") + .description("Color of the pop counter text.") + .defaultValue(new SettingColor(255, 80, 80, 255)) + .build() + ); + + private final Setting gearColorHigh = sgColors.add(new ColorSetting.Builder() + .name("gear-color-high") + .defaultValue(new SettingColor(80, 220, 80, 255)) + .build() + ); + + private final Setting gearColorLow = sgColors.add(new ColorSetting.Builder() + .name("gear-color-low") + .defaultValue(new SettingColor(220, 60, 60, 255)) + .build() + ); + + private final Setting customScale = sgScale.add(new BoolSetting.Builder() + .name("custom-scale") + .defaultValue(false) + .build() + ); + + private final Setting scale = sgScale.add(new DoubleSetting.Builder() + .name("scale") + .defaultValue(1.0) + .min(0.5) + .sliderRange(0.5, 3.0) + .visible(customScale::get) + .build() + ); + + private final Setting iconScale = sgScale.add(new DoubleSetting.Builder() + .name("icon-scale") + .description("Scale multiplier for armor and hand item icons.") + .defaultValue(1.0) + .min(0.5) + .sliderRange(0.5, 2.0) + .build() + ); + private static final int PADDING = 6; + private static final int BOTTOM_PADDING = 8; + private static final int BAR_HEIGHT = 5; + private static final int HAND_COLUMN_WIDTH = 28; + private static final float HAND_ITEM_SCALE_BASE = 1.4f; + private static final int HAND_ITEM_SIZE_BASE = (int)(16 * HAND_ITEM_SCALE_BASE); + private static final int BORDER = 1; + private static final int CONTENT_BASE_WIDTH = 220; // width of the info area (excluding face and hands) + + private static final EquipmentSlot[] ARMOR_SLOTS = { + EquipmentSlot.HEAD, + EquipmentSlot.CHEST, + EquipmentSlot.LEGS, + EquipmentSlot.FEET + }; + + private int lastHeight = 60; + + public GenyoTargetHud() { + super(INFO); + } + + @Override + public void tick(HudRenderer renderer) { + LivingEntity target = getTarget(); + if (target == null) { + if (isInEditor()) setSize(getPanelWidth(), getRequiredHeight(null, renderer)); + else setSize(0, 0); + return; + } + lastHeight = getRequiredHeight(target, renderer); + setSize(getPanelWidth(), lastHeight); + } + + + // Render + @Override + public void render(HudRenderer renderer) { + LivingEntity target = getTarget(); + + if (target == null) { + if (isInEditor()) renderer.text("Target HUD", x, y, textColor.get(), shadow.get(), getScale()); + return; + } + + int pw = getPanelWidth(); + int ph = getRequiredHeight(target, renderer); + double cx = x; + double cy = y; + + // Background + renderer.quad(cx, cy, pw, ph, bgColor.get()); + + + Color bc = borderColor.get(); + renderer.quad(cx, cy, pw, BORDER, bc); // top + renderer.quad(cx, cy + ph - BORDER, pw, BORDER, bc); // bottom + renderer.quad(cx, cy, BORDER, ph, bc); // left + renderer.quad(cx + pw - BORDER, cy, BORDER, ph, bc); // right + + int faceSize = 0; + if (showFace.get() && target instanceof PlayerEntity facePlayer) { + faceSize = ph; + PlayerListEntry entry = mc.getNetworkHandler() != null + ? mc.getNetworkHandler().getPlayerListEntry(facePlayer.getUuid()) : null; + if (entry != null) { + if (flatFace.get()) { + net.minecraft.util.Identifier skinTex = entry.getSkinTextures().body().texturePath(); + + int drawX = (int)cx + BORDER; + int drawY = (int)cy + BORDER; + int size = faceSize - BORDER * 2; + + var tex = mc.getTextureManager().getTexture(skinTex); + + meteordevelopment.meteorclient.renderer.Renderer2D.TEXTURE.begin(); + meteordevelopment.meteorclient.renderer.Renderer2D.TEXTURE.texQuad( + drawX, drawY, size, size, + 0, // rotation + 8f/64f, 8f/64f, // texX1, texY1 + 16f/64f, 16f/64f, // texX2, texY2 + Color.WHITE + ); + meteordevelopment.meteorclient.renderer.Renderer2D.TEXTURE.render( + tex.getGlTextureView(), tex.getSampler() + ); + + meteordevelopment.meteorclient.renderer.Renderer2D.TEXTURE.begin(); + meteordevelopment.meteorclient.renderer.Renderer2D.TEXTURE.texQuad( + drawX, drawY, size, size, + 0, + 40f/64f, 8f/64f, + 48f/64f, 16f/64f, + Color.WHITE + ); + meteordevelopment.meteorclient.renderer.Renderer2D.TEXTURE.render( + tex.getGlTextureView(), tex.getSampler() + ); + } else { + ItemStack skull = new ItemStack(Items.PLAYER_HEAD); + skull.set(DataComponentTypes.PROFILE, + ProfileComponent.ofStatic(facePlayer.getGameProfile())); + + float itemScale = (faceSize - BORDER * 2) / 16f; + int drawX = (int)cx + BORDER; + int drawY = (int)cy + BORDER; + renderer.item(skull, drawX, drawY, itemScale, false); + } + } + renderer.quad(cx + faceSize, cy, 1, ph, borderColor.get()); + } + + int accentX = (int)cx + faceSize; + renderer.quad(accentX, cy, 2, ph, getHealthColor(target)); + + int handColX = (int)(cx + pw - HAND_COLUMN_WIDTH - PADDING); + if (showHands.get() && target instanceof PlayerEntity player) { + renderer.quad(handColX - 1, cy + PADDING, 1, ph - PADDING * 2, + new Color(80, 80, 80, 120)); + + float handItemScale = HAND_ITEM_SCALE_BASE * (float)(double) iconScale.get(); + int handItemSize = (int)(16 * handItemScale); + ItemStack mainHand = player.getMainHandStack(); + ItemStack offHand = player.getOffHandStack(); + int totalHandH = handItemSize * 2 + 4; + int handStartY = (int)(cy + (ph - totalHandH) / 2.0); + int handX = handColX + (HAND_COLUMN_WIDTH - handItemSize) / 2; + + if (!mainHand.isEmpty()) renderer.item(mainHand, handX, handStartY, handItemScale, true); + if (!offHand.isEmpty()) renderer.item(offHand, handX, handStartY + handItemSize + 4, handItemScale, true); + } + + int contentEndX = showHands.get() ? handColX - PADDING : (int)(cx + pw - PADDING); + int textStartX = accentX + 2 + PADDING; + int barW = contentEndX - textStartX; + double curY = cy + PADDING; + + String name = target.getName().getString(); + String sourceTag = showSource.get() ? " " + getSource(target) : ""; + double curX = textStartX; + renderer.text(name, curX, curY, nameColor.get(), shadow.get(), getScale()); + curX += renderer.textWidth(name, shadow.get(), getScale()); + if (!sourceTag.isEmpty()) { + renderer.text(sourceTag, curX, curY, new Color(160, 160, 160, 200), shadow.get(), getScale()); + curX += renderer.textWidth(sourceTag, shadow.get(), getScale()); + } + if (showPops.get() && target instanceof PlayerEntity popPlayer) { + Integer pops = Managers.COMBAT.popList.get(popPlayer.getName().getString()); + if (pops != null && pops > 0) { + String popText = " -" + pops; + renderer.text(popText, curX, curY, popColor.get(), shadow.get(), getScale()); + } + } + curY += renderer.textHeight(shadow.get(), getScale()) + 2; + + if (showHealth.get()) { + float health = target.getHealth(); + float absorption = target.getAbsorptionAmount(); + float maxHealth = target.getMaxHealth(); + float healthPct = MathHelper.clamp(health / maxHealth, 0f, 1f); + + renderer.quad(textStartX, curY, barW, BAR_HEIGHT, new Color(40, 40, 40, 180)); + renderer.quad(textStartX, curY, (int)(barW * healthPct), BAR_HEIGHT, getHealthColor(target)); + + if (absorption > 0) { + float absPct = MathHelper.clamp(absorption / maxHealth, 0f, 1f); + int absW = (int)(barW * absPct); + int fillW = (int)(barW * healthPct); + int absX = Math.max(textStartX, textStartX + fillW - absW); + renderer.quad(absX, curY, absW, BAR_HEIGHT, new Color(255, 220, 80, 120)); + } + curY += BAR_HEIGHT + 2; + + String healthText = String.format("%.1f / %.1f", health, maxHealth); + if (absorption > 0) healthText += String.format(" (+%.1f)", absorption); + renderer.text(healthText, textStartX, curY, textColor.get(), shadow.get(), getScale()); + curY += renderer.textHeight(shadow.get(), getScale()) + 2; + } + + if (target instanceof PlayerEntity player) { + List durs = getArmorDurabilities(player); + int slotCount = 4; + int gap = 2; + int slotW = (barW - gap * (slotCount - 1)) / slotCount; + + float itemScale = Math.min((float) slotW / 16f, 1.5f) * (float)(double) iconScale.get(); + int itemRenderSize = (int)(16 * itemScale); + + if (showArmorItems.get()) { + int itemOffsetY = (int) curY; + for (int i = 0; i < slotCount; i++) { + ItemStack stack = player.getEquippedStack(ARMOR_SLOTS[i]); + if (!stack.isEmpty()) { + int slotX = textStartX + i * (slotW + gap); + int itemX = slotX + (slotW - itemRenderSize) / 2; + renderer.item(stack, itemX, itemOffsetY, itemScale, true); + } + } + curY += itemRenderSize + 3; + } + + if (showArmor.get()) { + for (int i = 0; i < slotCount; i++) { + float dur = durs.get(i)[0]; + boolean has = durs.get(i)[1] > 0; + int slotX = textStartX + i * (slotW + gap); + + renderer.quad(slotX, curY, slotW, BAR_HEIGHT, new Color(40, 40, 40, 180)); + if (has) { + Color fill = dur < 0.2f ? new Color(220, 60, 60, 255) : armorColor.get(); + renderer.quad(slotX, curY, (int)(slotW * dur), BAR_HEIGHT, fill); + } + } + curY += BAR_HEIGHT + 2; + } + + if (showGearPercent.get()) { + if (perPieceGear.get()) { + for (int i = 0; i < slotCount; i++) { + float dur = durs.get(i)[0]; + boolean has = durs.get(i)[1] > 0; + if (!has) continue; + String label = String.format("%.0f%%", dur * 100f); + Color col = interpolateColor(gearColorLow.get(), gearColorHigh.get(), dur); + double lw = renderer.textWidth(label, shadow.get(), getScale()); + double slotCentX = textStartX + i * (slotW + gap) + slotW / 2.0; + renderer.text(label, slotCentX - lw / 2.0, curY, col, shadow.get(), getScale()); + } + } else { + float gearPct = getGearPercent(player); + String gearText = String.format("Gear: %.0f%%", gearPct * 100f); + Color gearCol = interpolateColor(gearColorLow.get(), gearColorHigh.get(), gearPct); + renderer.text(gearText, textStartX, curY, gearCol, shadow.get(), getScale()); + } + curY += renderer.textHeight(shadow.get(), getScale()) + 2; + } + } + + boolean hasDistance = showDistance.get(); + boolean hasPing = showPing.get() && target instanceof PlayerEntity; + if (hasDistance || hasPing) { + renderer.quad(textStartX, curY, barW, 1, new Color(80, 80, 80, 140)); + curY += 4; + + String distText = hasDistance ? String.format("%.1fm", mc.player.distanceTo(target)) : null; + String pingText = null; + if (hasPing) { + int ping = getPing((PlayerEntity) target); + if (ping >= 0) pingText = ping + "ms"; + } + + if (distText != null && pingText != null) { + double distW = renderer.textWidth(distText, shadow.get(), getScale()); + double pingW = renderer.textWidth(pingText, shadow.get(), getScale()); + double textH = renderer.textHeight(shadow.get(), getScale()); + double totalW = distW + 9 + pingW; + double startX = textStartX + (barW - totalW) / 2.0; + + renderer.text(distText, startX, curY, textColor.get(), shadow.get(), getScale()); + double divX = startX + distW + 4; + renderer.quad(divX, curY - 1, 1, (int)textH + 2, new Color(100, 100, 100, 160)); + renderer.text(pingText, divX + 5, curY, textColor.get(), shadow.get(), getScale()); + } else { + String single = distText != null ? distText : pingText; + if (single != null) + renderer.text(single, textStartX, curY, textColor.get(), shadow.get(), getScale()); + } + } + } + + private LivingEntity getTarget() { + GenyoAutoCrystal crystal = Modules.get().get(GenyoAutoCrystal.class); + if (Modules.get().isActive(GenyoAutoCrystal.class) && crystal.targetEntity != null) + return crystal.targetEntity; + KFCSpawnKill kfc = Modules.get().get(KFCSpawnKill.class); + if (Modules.get().isActive(KFCSpawnKill.class)) { + Entity e = kfc.getEntityTarget(); + if (e instanceof LivingEntity living) return living;}return null;} + + private String getSource(LivingEntity target) { + GenyoAutoCrystal crystal = Modules.get().get(GenyoAutoCrystal.class); + if (Modules.get().isActive(GenyoAutoCrystal.class) && crystal.targetEntity == target) return "[AC]";return "[KA]";} + + private Color getHealthColor(LivingEntity target) { + float t = MathHelper.clamp(target.getHealth() / target.getMaxHealth(), 0f, 1f); + return interpolateColor(healthColorLow.get(), healthColorHigh.get(), t);} + + private Color interpolateColor(SettingColor lo, SettingColor hi, float t) { + return new Color( + (int)(lo.r + (hi.r - lo.r) * t), + (int)(lo.g + (hi.g - lo.g) * t), + (int)(lo.b + (hi.b - lo.b) * t), + 255);} + + private List getArmorDurabilities(PlayerEntity player) { + List result = new ArrayList<>(); + for (EquipmentSlot slot : ARMOR_SLOTS) { + ItemStack stack = player.getEquippedStack(slot); + if (stack.isEmpty() || stack.getMaxDamage() == 0) { + result.add(new float[]{ 0f, 0f }); + } else { + result.add(new float[]{ + 1f - (stack.getDamage() / (float) stack.getMaxDamage()), + stack.getMaxDamage() + }); + } + }return result;} + + private float getGearPercent(PlayerEntity player) { + float total = 0f; + int count = 0; + for (EquipmentSlot slot : ARMOR_SLOTS) { + ItemStack stack = player.getEquippedStack(slot); + if (!stack.isEmpty() && stack.getMaxDamage() > 0) { + total += 1f - (stack.getDamage() / (float) stack.getMaxDamage()); + count++; + } + } + return count == 0 ? 1f : total / count; + } + + private int getPing(PlayerEntity player) { + PlayerListEntry entry = mc.getNetworkHandler() != null + ? mc.getNetworkHandler().getPlayerListEntry(player.getUuid()) : null; + return entry != null ? entry.getLatency() : -1; + } + + private int getPanelWidth() { + int handExtra = showHands.get() ? HAND_COLUMN_WIDTH + PADDING : 0; + int faceExtra = showFace.get() ? lastHeight : 0; + return CONTENT_BASE_WIDTH + handExtra + faceExtra; + } + + private int getRequiredHeight(LivingEntity target, HudRenderer renderer) { + boolean isPlayer = target == null || target instanceof PlayerEntity; + + double textH = renderer.textHeight(shadow.get(), getScale()); + + double h = PADDING + textH + 2; // top padding + name row + + if (showHealth.get()) h += BAR_HEIGHT + 2 + textH + 2; + + if (isPlayer) { + float itemScaleEst = Math.min(((CONTENT_BASE_WIDTH - PADDING * 2 - 2 - 3 * 2) / 4) / 16f, 1.5f) + * (float)(double) iconScale.get(); + int itemSizeEst = (int)(16 * itemScaleEst); + + if (showArmorItems.get()) h += itemSizeEst + 3; + if (showArmor.get()) h += BAR_HEIGHT + 2; + if (showGearPercent.get()) h += textH + 2; + } + + if (showDistance.get() || showPing.get()) + h += 1 + 4 + textH; + + h += BOTTOM_PADDING; + + if (showHands.get()) h = Math.max(h, HAND_ITEM_SIZE_BASE * 2 + 4 + PADDING * 2); + + return (int) Math.ceil(h); + } + + private double getScale() { + return customScale.get() ? scale.get() : Hud.get().getTextScale(); + } +} diff --git a/src/main/java/com/genyo/systems/hud/LogoHud.java b/src/main/java/com/genyo/systems/hud/LogoHud.java index e12f564..6447bd6 100644 --- a/src/main/java/com/genyo/systems/hud/LogoHud.java +++ b/src/main/java/com/genyo/systems/hud/LogoHud.java @@ -1,7 +1,6 @@ package com.genyo.systems.hud; import com.genyo.Genyo; -import meteordevelopment.meteorclient.renderer.GL; import meteordevelopment.meteorclient.renderer.Renderer2D; import meteordevelopment.meteorclient.settings.DoubleSetting; import meteordevelopment.meteorclient.settings.Setting; @@ -9,8 +8,9 @@ import meteordevelopment.meteorclient.systems.hud.HudElement; import meteordevelopment.meteorclient.systems.hud.HudElementInfo; import meteordevelopment.meteorclient.systems.hud.HudRenderer; +import net.minecraft.client.MinecraftClient; import meteordevelopment.meteorclient.utils.render.color.Color; -import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.texture.AbstractTexture; import net.minecraft.util.Identifier; public class LogoHud extends HudElement { @@ -36,11 +36,11 @@ public LogoHud() { @Override public void render(HudRenderer renderer) { setSize(256 * scale.get(), 256 * scale.get()); - MatrixStack matrices = new MatrixStack(); - GL.bindTexture(logo); + AbstractTexture texture = MinecraftClient.getInstance().getTextureManager().getTexture(logo); + Renderer2D.TEXTURE.begin(); Renderer2D.TEXTURE.texQuad(x, y, 256 * scale.get(), 256 * scale.get(), new Color(255, 255, 255, 255)); - Renderer2D.TEXTURE.render(matrices); + Renderer2D.TEXTURE.render(texture.getGlTextureView(), texture.getSampler()); } } diff --git a/src/main/java/com/genyo/systems/modules/combat/AutoCrawlTrap.java b/src/main/java/com/genyo/systems/modules/combat/AutoCrawlTrap.java index 8c0abae..252cdbf 100644 --- a/src/main/java/com/genyo/systems/modules/combat/AutoCrawlTrap.java +++ b/src/main/java/com/genyo/systems/modules/combat/AutoCrawlTrap.java @@ -321,8 +321,8 @@ public List getCrawlTrap(PlayerEntity entity, BlockPos playerPos) int ticks = 0; while (ticks <= extrapolateTicks.get()) { - double ox = (x - entity.prevX) * ticks; - double oz = (z - entity.prevZ) * ticks; + double ox = (x - entity.lastX) * ticks; + double oz = (z - entity.lastZ) * ticks; BlockPos blockPos = BlockPos.ofFloored(x + ox, y, z + oz); if (!crawlTrap.contains(blockPos.up())) { diff --git a/src/main/java/com/genyo/systems/modules/combat/BasePlace.java b/src/main/java/com/genyo/systems/modules/combat/BasePlace.java index 496aa11..a5d5e65 100644 --- a/src/main/java/com/genyo/systems/modules/combat/BasePlace.java +++ b/src/main/java/com/genyo/systems/modules/combat/BasePlace.java @@ -14,7 +14,8 @@ import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.systems.modules.combat.CrystalAura; -import meteordevelopment.meteorclient.systems.modules.world.AirPlace; + +import meteordevelopment.meteorclient.systems.modules.player.AirPlace; import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.render.color.SettingColor; import meteordevelopment.orbit.EventHandler; diff --git a/src/main/java/com/genyo/systems/modules/combat/FriendProtector.java b/src/main/java/com/genyo/systems/modules/combat/FriendProtector.java index cbf5734..52e3a23 100644 --- a/src/main/java/com/genyo/systems/modules/combat/FriendProtector.java +++ b/src/main/java/com/genyo/systems/modules/combat/FriendProtector.java @@ -15,7 +15,7 @@ import meteordevelopment.meteorclient.renderer.ShapeMode; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Modules; -import meteordevelopment.meteorclient.systems.modules.world.AirPlace; +import meteordevelopment.meteorclient.systems.modules.player.AirPlace; import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.render.color.SettingColor; import meteordevelopment.orbit.EventHandler; diff --git a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoArmor.java b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoArmor.java index 0eac8be..151de41 100644 --- a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoArmor.java +++ b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoArmor.java @@ -83,6 +83,13 @@ public GenyoAutoArmor() { private final Queue leggings = new PriorityQueue<>(); private final Queue boots = new PriorityQueue<>(); + private static final EquipmentSlot[] ARMOR_SLOTS = { + EquipmentSlot.HEAD, + EquipmentSlot.CHEST, + EquipmentSlot.LEGS, + EquipmentSlot.FEET + }; + @EventHandler public void onTick(PlayerTickEvent event) { @@ -123,7 +130,7 @@ public void onTick(PlayerTickEvent event) } for (int i = 0; i < 4; i++) { - ItemStack armorStack = mc.player.getInventory().getArmorStack(i); + ItemStack armorStack = mc.player.getEquippedStack(ARMOR_SLOTS[i]); if (elytraPriorityConfig.get() && armorStack.getItem() == Items.ELYTRA) { continue; diff --git a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoCrystal.java b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoCrystal.java index b16da12..7882909 100644 --- a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoCrystal.java +++ b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoCrystal.java @@ -7,6 +7,7 @@ import com.genyo.systems.modules.misc.FastLatency; import com.genyo.systems.settings.FloatSetting; import com.genyo.utils.player.RotationUtil; +import com.genyo.utils.world.ExplosionUtil; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.render.color.SettingColor; @@ -24,7 +25,6 @@ import com.genyo.utils.player.InventoryUtil; import com.genyo.utils.player.PlayerUtil; import com.genyo.utils.world.BlastResistantBlocks; -import com.genyo.utils.world.ExplosionUtil; import com.google.common.collect.Lists; import meteordevelopment.meteorclient.events.packets.PacketEvent; import meteordevelopment.meteorclient.events.render.Render2DEvent; @@ -38,7 +38,6 @@ import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.ShulkerBoxBlock; -import net.minecraft.component.type.AttributeModifierSlot; import net.minecraft.entity.*; import net.minecraft.entity.decoration.EndCrystalEntity; import net.minecraft.entity.effect.StatusEffectInstance; @@ -701,7 +700,7 @@ public void onPlayerUpdate(PlayerTickEvent event) } renderPos = null; ArrayList entities = Lists.newArrayList(mc.world.getEntities()); - List blocks = getSphere(placeRangeEye.get() ? mc.player.getEyePos() : mc.player.getPos()); + List blocks = getSphere(placeRangeEye.get() ? mc.player.getEyePos() : mc.player.getEntityPos()); long timePre = System.nanoTime(); if (place.get()) { @@ -718,7 +717,7 @@ public void onPlayerUpdate(PlayerTickEvent event) EndCrystalEntity crystalEntity = intersectingCrystalCheck(placeCrystal.getDamageData()); if (crystalEntity != null) { - double self = ExplosionUtil.getDamageTo(mc.player, crystalEntity.getPos(), + double self = ExplosionUtil.getDamageTo(mc.player, crystalEntity.getEntityPos(), blockDestruction.get(), selfExtrapolate.get() ? extrapolateTicks.get() : 0, false); if (!safety.get() || !playerDamageCheck(self)) { @@ -757,7 +756,7 @@ public void onPlayerUpdate(PlayerTickEvent event) attackRotate = attackCrystal != null && attackDelay.get() <= 0.0 && lastAttackTimer.passed(breakDelay); if (attackCrystal != null) { - crystalRotation = attackCrystal.damageData.getPos(); + crystalRotation = attackCrystal.damageData.getEntityPos(); } else if (placeCrystal != null) { @@ -1017,7 +1016,7 @@ public void onAddEntity(AddEntityEvent event) { return; } - Vec3d crystalPos = crystalEntity.getPos(); + Vec3d crystalPos = crystalEntity.getEntityPos(); BlockPos blockPos = BlockPos.ofFloored(crystalPos.add(0.0, -1.0, 0.0)); renderSpawnPos = blockPos; Long time = placePackets.remove(blockPos); @@ -1061,7 +1060,7 @@ else if (instantCalc.get()) { continue; } - double crystalDist = crystalPos.squaredDistanceTo(entity.getPos()); + double crystalDist = crystalPos.squaredDistanceTo(entity.getEntityPos()); if (crystalDist > 144.0f) { continue; @@ -1135,9 +1134,9 @@ public void attackCrystal(EndCrystalEntity entity, Hand hand) for (int i = 0; i < 9; ++i) { ItemStack stack = mc.player.getInventory().getStack(i); - if (!stack.isEmpty() && (stack.getItem() instanceof SwordItem + if (!stack.isEmpty() && (stack.isIn(ItemTags.SWORDS) || stack.getItem() instanceof AxeItem - || stack.getItem() instanceof PickaxeItem)) + || stack.isIn(ItemTags.PICKAXES))) { slot = i; break; @@ -1151,7 +1150,7 @@ public void attackCrystal(EndCrystalEntity entity, Hand hand) if (antiWeakness.get() == Swap.SILENT_ALT) { mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, - slot + 36, mc.player.getInventory().selectedSlot, SlotActionType.SWAP, mc.player); + slot + 36, mc.player.getInventory().getSelectedSlot(), SlotActionType.SWAP, mc.player); } else if (antiWeakness.get() == Swap.SILENT) { @@ -1168,7 +1167,7 @@ else if (antiWeakness.get() == Swap.SILENT) if (antiWeakness.get() == Swap.SILENT_ALT) { mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, - slot + 36, mc.player.getInventory().selectedSlot, SlotActionType.SWAP, mc.player); + slot + 36, mc.player.getInventory().getSelectedSlot(), SlotActionType.SWAP, mc.player); } else if (antiWeakness.get() == Swap.SILENT) { @@ -1279,7 +1278,7 @@ public void placeCrystal(BlockPos blockPos, Hand hand, boolean checkPlacement) if (autoSwap.get() == Swap.SILENT_ALT) { mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, - crystalSlot + 36, mc.player.getInventory().selectedSlot, SlotActionType.SWAP, mc.player); + crystalSlot + 36, mc.player.getInventory().getSelectedSlot(), SlotActionType.SWAP, mc.player); } else if (autoSwap.get() == Swap.SILENT) { @@ -1297,7 +1296,7 @@ else if (autoSwap.get() == Swap.SILENT) if (autoSwap.get() == Swap.SILENT_ALT) { mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, - crystalSlot + 36, mc.player.getInventory().selectedSlot, SlotActionType.SWAP, mc.player); + crystalSlot + 36, mc.player.getInventory().getSelectedSlot(), SlotActionType.SWAP, mc.player); } else if (autoSwap.get() == Swap.SILENT) { @@ -1437,7 +1436,7 @@ private DamageData calculateAttackCrystal(List entitie { continue; } - double selfDamage = ExplosionUtil.getDamageTo(mc.player, crystal.getPos(), + double selfDamage = ExplosionUtil.getDamageTo(mc.player, crystal.getEntityPos(), blockDestruction.get(), selfExtrapolate.get() ? extrapolateTicks.get() : 0, false); boolean unsafeToPlayer = playerDamageCheck(selfDamage); if (unsafeToPlayer && !safetyOverride.get()) @@ -1495,7 +1494,7 @@ private DamageData calculateAttackCrystal(List entitie } } - double damage = ExplosionUtil.getDamageTo(entity, crystal.getPos(), blockDestruction.get(), + double damage = ExplosionUtil.getDamageTo(entity, crystal.getEntityPos(), blockDestruction.get(), extrapolateTicks.get(), assumeArmor.get()); if (checkOverrideSafety(unsafeToPlayer, damage, entity)) { @@ -1528,7 +1527,7 @@ private DamageData calculateAttackCrystal(List entitie private boolean attackRangeCheck(EndCrystalEntity entity) { - return attackRangeCheck(entity.getPos()); + return attackRangeCheck(entity.getEntityPos()); } /** @@ -1587,7 +1586,7 @@ private DamageData calculatePlaceCrystal(List placeBlocks, L { continue; } - double blockDist = pos.getSquaredDistance(entity.getPos()); + double blockDist = pos.getSquaredDistance(entity.getEntityPos()); if (blockDist > 144.0f) { continue; @@ -1670,7 +1669,7 @@ private boolean placeRangeCheck(BlockPos pos) { double placeRange = placeRangeC.get(); double placeWallRange = placeWallRangeC.get(); - Vec3d player = placeRangeEye.get() ? mc.player.getEyePos() : mc.player.getPos(); + Vec3d player = placeRangeEye.get() ? mc.player.getEyePos() : mc.player.getEntityPos(); double dist = placeRangeCenter.get() ? player.squaredDistanceTo(pos.toCenterPos()) : pos.getSquaredDistance(player.x, player.y, player.z); if (dist > placeRange * placeRange) @@ -1812,8 +1811,9 @@ private boolean isCrystalLethalTo(double damage, LivingEntity entity) } if (armorBreaker.get()) { - for (ItemStack armorStack : entity.getArmorItems()) + for (EquipmentSlot slot : new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}) { + ItemStack armorStack = entity.getEquippedStack(slot); int n = armorStack.getDamage(); int n1 = armorStack.getMaxDamage(); float durability = ((n1 - n) / (float) n1) * 100.0f; @@ -1827,7 +1827,7 @@ private boolean isCrystalLethalTo(double damage, LivingEntity entity) // Antiregear if (shulkers.get() && entity instanceof PlayerEntity) { - for (BlockPos pos : getSphere(3.0f, entity.getPos())) + for (BlockPos pos : getSphere(3.0f, entity.getEntityPos())) { BlockState state = mc.world.getBlockState(pos); if (state.getBlock() instanceof ShulkerBoxBlock) @@ -1954,7 +1954,7 @@ else if (entity instanceof EndCrystalEntity entity1 else { double dist = mc.player.squaredDistanceTo(entity1); - stuckCrystals.add(new AntiStuckData(entity1.getId(), entity1.getBlockPos(), entity1.getPos(), dist)); + stuckCrystals.add(new AntiStuckData(entity1.getId(), entity1.getBlockPos(), entity1.getEntityPos(), dist)); } } } diff --git a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoTotem.java b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoTotem.java index 91331f0..179d0d3 100644 --- a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoTotem.java +++ b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoTotem.java @@ -220,7 +220,7 @@ public void onTick(TickEvent.Pre event) // If offhand gap is enabled & the use key is pressed down, equip a golden apple. final Item mainHandItem = mc.player.getMainHandStack().getItem(); if (gappleConfig.get() && mc.options.useKey.isPressed() - && (mainHandItem instanceof SwordItem + && (mc.player.getMainHandStack().isIn(ItemTags.SWORDS) || mainHandItem instanceof TridentItem || mainHandItem instanceof AxeItem) && PlayerUtil.getLocalPlayerHealth() >= healthConfig.get()) @@ -366,7 +366,7 @@ private boolean checkLethalCrystal(float health) { continue; } - double potential = ExplosionUtil.getDamageTo(mc.player, crystal.getPos(), false); + double potential = ExplosionUtil.getDamageTo(mc.player, crystal.getEntityPos(), false); if (health + 0.5 > potential) { continue; diff --git a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoTrap.java b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoTrap.java index 73c10ae..a9f8ad4 100644 --- a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoTrap.java +++ b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoTrap.java @@ -15,7 +15,7 @@ import meteordevelopment.meteorclient.renderer.ShapeMode; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Modules; -import meteordevelopment.meteorclient.systems.modules.world.AirPlace; +import meteordevelopment.meteorclient.systems.modules.player.AirPlace; import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.render.color.SettingColor; import meteordevelopment.orbit.EventHandler; diff --git a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoXP.java b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoXP.java index c1abad2..b0918fb 100644 --- a/src/main/java/com/genyo/systems/modules/combat/GenyoAutoXP.java +++ b/src/main/java/com/genyo/systems/modules/combat/GenyoAutoXP.java @@ -139,8 +139,9 @@ private boolean areItemsFullDura(PlayerEntity player) return false; } - for (ItemStack stack : player.getArmorItems()) + for (EquipmentSlot slot : new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}) { + ItemStack stack = player.getEquippedStack(slot); if (!isItemFullDura(stack)) { return false; diff --git a/src/main/java/com/genyo/systems/modules/combat/KFCSpawnKill.java b/src/main/java/com/genyo/systems/modules/combat/KFCSpawnKill.java index a129205..190e0d6 100644 --- a/src/main/java/com/genyo/systems/modules/combat/KFCSpawnKill.java +++ b/src/main/java/com/genyo/systems/modules/combat/KFCSpawnKill.java @@ -493,7 +493,7 @@ public void onPlayerUpdate(PlayerTickEvent event) if (attackDelayConfig.get()) { PlayerInventory inventory = mc.player.getInventory(); - ItemStack itemStack = inventory.getStack((slot == -1 || !swordCheckConfig.get()) ? mc.player.getInventory().selectedSlot : slot); + ItemStack itemStack = inventory.getStack((slot == -1 || !swordCheckConfig.get()) ? mc.player.getInventory().getSelectedSlot() : slot); MutableDouble attackSpeed = new MutableDouble( mc.player.getAttributeBaseValue(EntityAttributes.ATTACK_SPEED)); @@ -643,11 +643,10 @@ private int getSwordSlot() for (int i = 0; i < 9; i++) { final ItemStack stack = mc.player.getInventory().getStack(i); - if (stack.getItem() instanceof SwordItem swordItem) + if (stack.isIn(ItemTags.SWORDS)) { - float sharpness = EnchantmentUtil.getLevel(stack, - Enchantments.SHARPNESS) * 0.5f + 0.5f; - float dmg = swordItem.getDefaultStack().getDamage() + sharpness; + float sharpness = EnchantmentUtil.getLevel(stack, Enchantments.SHARPNESS) * 0.5f + 0.5f; + float dmg = stack.getItem().getDefaultStack().getDamage() + sharpness; if (dmg > sharp) { sharp = dmg; @@ -734,8 +733,7 @@ private void preAttackTarget() sneaking = Managers.POSITION.isSneaking(); if (sneaking) { - Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, - ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY)); + mc.player.setSneaking(false); } sprinting = Managers.POSITION.isSprinting(); if (sprinting) @@ -756,8 +754,7 @@ private void postAttackTarget(Entity entity) } if (sneaking) { - Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, - ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY)); + mc.player.setSneaking(true); } if (sprinting) { @@ -797,11 +794,11 @@ private Entity getAttackTarget(Vec3d pos) } if (armorCheckConfig.get() && entity instanceof LivingEntity livingEntity - && !livingEntity.getArmorItems().iterator().hasNext()) + && !Stream.of(EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET).anyMatch(s -> !livingEntity.getEquippedStack(s).isEmpty())) { continue; } - double dist = pos.distanceTo(entity.getPos()); + double dist = pos.distanceTo(entity.getEntityPos()); if (dist <= searchRangeConfig.get()) { if (entity.age < ticksExistedConfig.get()) @@ -852,8 +849,9 @@ private float getArmorDurability(LivingEntity e) { float edmg = 0.0f; float emax = 0.0f; - for (ItemStack armor : e.getArmorItems()) + for (EquipmentSlot s : new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}) { + ItemStack armor = e.getEquippedStack(s); if (armor != null && !armor.isEmpty()) { edmg += armor.getDamage(); @@ -905,7 +903,7 @@ public boolean isInAttackRange(double dist, Vec3d pos, Vec3d entityPos) public boolean isHoldingSword() { - return !swordCheckConfig.get() || mc.player.getMainHandStack().getItem() instanceof SwordItem + return !swordCheckConfig.get() || mc.player.getMainHandStack().isIn(ItemTags.SWORDS) || mc.player.getMainHandStack().getItem() instanceof AxeItem || mc.player.getMainHandStack().getItem() instanceof TridentItem || mc.player.getMainHandStack().getItem() instanceof MaceItem; @@ -913,7 +911,7 @@ public boolean isHoldingSword() private Vec3d getAttackRotateVec(Entity entity) { - Vec3d feetPos = entity.getPos(); + Vec3d feetPos = entity.getEntityPos(); return switch (hitVectorConfig.get()) { case FEET -> feetPos; diff --git a/src/main/java/com/genyo/systems/modules/misc/AutoOminous.java b/src/main/java/com/genyo/systems/modules/misc/AutoOminous.java index ef07efb..3449ebb 100644 --- a/src/main/java/com/genyo/systems/modules/misc/AutoOminous.java +++ b/src/main/java/com/genyo/systems/modules/misc/AutoOminous.java @@ -29,7 +29,7 @@ public AutoOminous() { public void onTick(TickEvent.Pre event) { if (mc.player == null || mc.world == null || mc.interactionManager == null || mc.getServer() == null) return; - RaidManager raidManager = mc.getServer().getWorld(mc.player.getWorld().getRegistryKey()).getRaidManager(); + RaidManager raidManager = mc.getServer().getWorld(mc.world.getRegistryKey()).getRaidManager(); if (raidManager == null) return; Raid raid = raidManager.getRaidAt(mc.player.getBlockPos(), 50); @@ -61,7 +61,7 @@ private void drinkPotion() { return; } - selectedSlot = mc.player.getInventory().selectedSlot; + selectedSlot = mc.player.getInventory().getSelectedSlot(); int itemSlot = result.slot(); boolean wasHeld = result.isMainHand(); diff --git a/src/main/java/com/genyo/systems/modules/misc/AutoRename.java b/src/main/java/com/genyo/systems/modules/misc/AutoRename.java index 02526c7..56dd33c 100644 --- a/src/main/java/com/genyo/systems/modules/misc/AutoRename.java +++ b/src/main/java/com/genyo/systems/modules/misc/AutoRename.java @@ -120,7 +120,7 @@ public AutoRename() { private boolean hasValidItems(AnvilScreenHandler handler) { if (mc.player == null) return false; - for (int n = 0; n < mc.player.getInventory().main.size() + ANVIL_OFFSET; n++) { + for (int n = 0; n < 36 + ANVIL_OFFSET; n++) { if (n == 2) continue; ItemStack stack = handler.getSlot(n).getStack(); if ((blacklistMode.get() && !itemList.get().contains(stack.getItem())) @@ -189,7 +189,7 @@ private void onTick(TickEvent.Post event) { if (!hasValidItems(anvil)) finished(); else if (input1.isEmpty() && input2.isEmpty()) { - for (int n = ANVIL_OFFSET; n < mc.player.getInventory().main.size() + ANVIL_OFFSET; n++) { + for (int n = ANVIL_OFFSET; n < 36 + ANVIL_OFFSET; n++) { ItemStack stack = anvil.getSlot(n).getStack(); if (stack.contains(DataComponentTypes.CUSTOM_NAME) && !renameNamed.get()) continue; else if (stack.getName().getString().equals(itemName.get())) continue; diff --git a/src/main/java/com/genyo/systems/modules/misc/CombatBrainrot.java b/src/main/java/com/genyo/systems/modules/misc/CombatBrainrot.java index 0d811f2..7bd782a 100644 --- a/src/main/java/com/genyo/systems/modules/misc/CombatBrainrot.java +++ b/src/main/java/com/genyo/systems/modules/misc/CombatBrainrot.java @@ -60,7 +60,7 @@ public void onPacketSend(PacketEvent.Send event) { if (mc.getServer() == null) return; if (event.packet instanceof PlayerInteractEntityC2SPacket packet) { - Entity entity = packet.getEntity(mc.getServer().getWorld(mc.player.getWorld().getRegistryKey())); + Entity entity = packet.getEntity(mc.getServer().getWorld(mc.world.getRegistryKey())); if (entity == null) return; if (entity instanceof EndCrystalEntity) { diff --git a/src/main/java/com/genyo/systems/modules/misc/GenyoAutoEZ.java b/src/main/java/com/genyo/systems/modules/misc/GenyoAutoEZ.java index 0f95ee8..d73e659 100644 --- a/src/main/java/com/genyo/systems/modules/misc/GenyoAutoEZ.java +++ b/src/main/java/com/genyo/systems/modules/misc/GenyoAutoEZ.java @@ -98,7 +98,7 @@ private void onReceive(PacketEvent.Receive event) { if (packet.getStatus() == 35) { //----Pop----// Entity entity = packet.getEntity(mc.world); if (mc.player != null && mc.world != null && entity instanceof PlayerEntity playerEntity) { - if (entity != mc.player && mc.player.getPos().distanceTo(entity.getPos()) <= range.get()) { + if (entity != mc.player && mc.player.getEntityPos().distanceTo(entity.getEntityPos()) <= range.get()) { if (trackPlayers.get()) { if (taggedPlayers.containsKey(playerEntity)) { diff --git a/src/main/java/com/genyo/systems/modules/misc/GenyoDiscord.java b/src/main/java/com/genyo/systems/modules/misc/GenyoDiscord.java index e0ba4a6..6c59e9c 100644 --- a/src/main/java/com/genyo/systems/modules/misc/GenyoDiscord.java +++ b/src/main/java/com/genyo/systems/modules/misc/GenyoDiscord.java @@ -18,7 +18,7 @@ import meteordevelopment.meteorclient.utils.Utils; import meteordevelopment.meteorclient.utils.misc.MeteorStarscript; import meteordevelopment.orbit.EventHandler; -import meteordevelopment.starscript.Script; +import org.meteordev.starscript.Script; import net.minecraft.client.gui.screen.*; import net.minecraft.client.gui.screen.multiplayer.AddServerScreen; import net.minecraft.client.gui.screen.multiplayer.ConnectScreen; diff --git a/src/main/java/com/genyo/systems/modules/misc/GenyoGoodbye.java b/src/main/java/com/genyo/systems/modules/misc/GenyoGoodbye.java index c187e13..9baf4f3 100644 --- a/src/main/java/com/genyo/systems/modules/misc/GenyoGoodbye.java +++ b/src/main/java/com/genyo/systems/modules/misc/GenyoGoodbye.java @@ -72,7 +72,7 @@ private void onReceivePacket(PacketEvent.Receive event) { PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(pac.profileIds().getFirst()); if (entry == null) return; - String name = entry.getProfile().getName(); + String name = entry.getProfile().name(); if (!namesList.contains(name)) return; handleMessage(name); diff --git a/src/main/java/com/genyo/systems/modules/misc/GenyoWelcome.java b/src/main/java/com/genyo/systems/modules/misc/GenyoWelcome.java index d38a37f..3ec3757 100644 --- a/src/main/java/com/genyo/systems/modules/misc/GenyoWelcome.java +++ b/src/main/java/com/genyo/systems/modules/misc/GenyoWelcome.java @@ -63,7 +63,7 @@ private void onGameJoined(GameJoinedEvent event) { if (mc.player == null && mc.world == null) return; onlinePlayers.clear(); mc.getNetworkHandler().getPlayerList().iterator().forEachRemaining(p -> { - if (p.getProfile() != null) onlinePlayers.add(p.getProfile().getId()); + if (p.getProfile() != null) onlinePlayers.add(p.getProfile().id()); }); } @@ -96,9 +96,9 @@ private void onReceivePacket(PacketEvent.Receive event) { GameProfile profile = entry.profile(); if (profile == null) return; - String name = profile.getName(); + String name = profile.name(); if (!namesList.contains(name)) return; - UUID playerUuid = profile.getId(); + UUID playerUuid = profile.id(); if (!pac.getActions().contains(PlayerListS2CPacket.Action.ADD_PLAYER) && playerUuid != null && !onlinePlayers.contains(playerUuid)) return; diff --git a/src/main/java/com/genyo/systems/modules/movement/GenyoNoSlow.java b/src/main/java/com/genyo/systems/modules/movement/GenyoNoSlow.java index 7b6ed32..190e398 100644 --- a/src/main/java/com/genyo/systems/modules/movement/GenyoNoSlow.java +++ b/src/main/java/com/genyo/systems/modules/movement/GenyoNoSlow.java @@ -26,6 +26,7 @@ import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.DeathScreen; import net.minecraft.client.gui.screen.ingame.SignEditScreen; +import net.minecraft.client.input.Input; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; import net.minecraft.component.DataComponentTypes; @@ -34,10 +35,9 @@ import net.minecraft.item.Items; import net.minecraft.network.packet.c2s.play.*; import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.MathHelper; +import com.genyo.mixin.accessor.AccessorInput; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.*; import org.lwjgl.glfw.GLFW; import java.util.ArrayList; @@ -179,8 +179,7 @@ public void onDeactivate() { if (airStrict.get() && sneaking) { - Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, - ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY)); + mc.player.setSneaking(false); } sneaking = false; Managers.TICK.setClientTick(1.0f); @@ -191,9 +190,7 @@ public void onSetCurrentHand(SetCurrentHandEvent event) { if (airStrict.get() && !sneaking && checkSlowed()) { - sneaking = true; - Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, - ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY)); + mc.player.setSneaking(true); } } @@ -226,26 +223,25 @@ public void onTick(TickEvent.Pre event) { if (airStrict.get() && !mc.player.isUsingItem()) { sneaking = false; - Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, - ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY)); + mc.player.setSneaking(false); } if (inventoryMove.get() && checkScreen()) { - final long handle = mc.getWindow().getHandle(); + KeyBinding[] keys = new KeyBinding[]{mc.options.jumpKey, mc.options.forwardKey, mc.options.backKey, mc.options.rightKey, mc.options.leftKey}; for (KeyBinding binding : keys) { - binding.setPressed(InputUtil.isKeyPressed(handle, ((AccessorKeyBinding) binding).getBoundKey().getCode())); + binding.setPressed(InputUtil.isKeyPressed(mc.getWindow(), ((AccessorKeyBinding) binding).getBoundKey().getCode())); } if (arrowMove.get()) { float yaw = mc.player.getYaw(); float pitch = mc.player.getPitch(); - if (InputUtil.isKeyPressed(handle, GLFW.GLFW_KEY_UP)) pitch -= 3.0f; - else if (InputUtil.isKeyPressed(handle, GLFW.GLFW_KEY_DOWN)) pitch += 3.0f; - else if (InputUtil.isKeyPressed(handle, GLFW.GLFW_KEY_LEFT)) yaw -= 3.0f; - else if (InputUtil.isKeyPressed(handle, GLFW.GLFW_KEY_RIGHT)) yaw += 3.0f; + if (InputUtil.isKeyPressed(mc.getWindow(), GLFW.GLFW_KEY_UP)) pitch -= 3.0f; + else if (InputUtil.isKeyPressed(mc.getWindow(), GLFW.GLFW_KEY_DOWN)) pitch += 3.0f; + else if (InputUtil.isKeyPressed(mc.getWindow(), GLFW.GLFW_KEY_LEFT)) yaw -= 3.0f; + else if (InputUtil.isKeyPressed(mc.getWindow(), GLFW.GLFW_KEY_RIGHT)) yaw += 3.0f; mc.player.setYaw(yaw); mc.player.setPitch(MathHelper.clamp(pitch, -90.0f, 90.0f)); @@ -304,14 +300,14 @@ public void onMovementSlowdown(MovementSlowdownEvent event) if (sneak.get() && mc.player.isSneaking() || crawl.get() && mc.player.isCrawling()) { float f = 1.0f / (float) mc.player.getAttributeValue(EntityAttributes.SNEAKING_SPEED); - event.input.movementForward *= f; - event.input.movementSideways *= f; + Vec2f vec = event.input.getMovementInput(); + ((AccessorInput) event.input).setMovementVector(new Vec2f(vec.x * f, vec.y * f)); } if (checkSlowed()) { - event.input.movementForward *= 5.0f; - event.input.movementSideways *= 5.0f; + Vec2f vec = event.input.getMovementInput(); + ((AccessorInput) event.input).setMovementVector(new Vec2f(vec.x * 5.0f, vec.y * 5.0f)); } } @@ -334,7 +330,6 @@ public void onBlockSlipperiness(BlockSlipperinessEvent event) event.slipperiness = 0.6f; } } - @EventHandler public void onPacketSend(PacketEvent.Send event) { @@ -342,7 +337,7 @@ public void onPacketSend(PacketEvent.Send event) else if (event.packet instanceof PlayerMoveC2SPacket packet && packet.changesPosition() && strict.get() && checkSlowed()) { - Managers.INVENTORY.setSlotForced(mc.player.getInventory().selectedSlot); + Managers.INVENTORY.setSlotForced(mc.player.getInventory().getSelectedSlot()); } else if (event.packet instanceof ClickSlotC2SPacket && strict.get()) { @@ -352,8 +347,7 @@ else if (event.packet instanceof ClickSlotC2SPacket && strict.get()) } if (sneaking || Managers.POSITION.isSneaking()) { - Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, - ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY)); + mc.player.setSneaking(false); } if (Managers.POSITION.isSprinting()) { diff --git a/src/main/java/com/genyo/systems/modules/movement/GenyoPhase.java b/src/main/java/com/genyo/systems/modules/movement/GenyoPhase.java index 7d337fd..6711f0e 100644 --- a/src/main/java/com/genyo/systems/modules/movement/GenyoPhase.java +++ b/src/main/java/com/genyo/systems/modules/movement/GenyoPhase.java @@ -268,7 +268,7 @@ else if (yaw1 >= 292.5 && yaw1 < 337.5) if (swapAltConfig.get()) { mc.interactionManager.clickSlot(0, pearlSlot < 9 ? pearlSlot + 36 : pearlSlot, 0, SlotActionType.PICKUP, mc.player); - mc.interactionManager.clickSlot(0, mc.player.getInventory().selectedSlot + 36, 0, SlotActionType.PICKUP, mc.player); + mc.interactionManager.clickSlot(0, mc.player.getInventory().getSelectedSlot() + 36, 0, SlotActionType.PICKUP, mc.player); mc.interactionManager.clickSlot(0, pearlSlot < 9 ? pearlSlot + 36 : pearlSlot, 0, SlotActionType.PICKUP, mc.player); } else if (pearlSlot < 9) @@ -291,7 +291,7 @@ else if (pearlSlot < 9) if (swapAltConfig.get()) { mc.interactionManager.clickSlot(0, pearlSlot < 9 ? pearlSlot + 36 : pearlSlot, 0, SlotActionType.PICKUP, mc.player); - mc.interactionManager.clickSlot(0, mc.player.getInventory().selectedSlot + 36, 0, SlotActionType.PICKUP, mc.player); + mc.interactionManager.clickSlot(0, mc.player.getInventory().getSelectedSlot() + 36, 0, SlotActionType.PICKUP, mc.player); mc.interactionManager.clickSlot(0, pearlSlot < 9 ? pearlSlot + 36 : pearlSlot, 0, SlotActionType.PICKUP, mc.player); } else if (pearlSlot < 9) diff --git a/src/main/java/com/genyo/systems/modules/movement/GenyoVelocity.java b/src/main/java/com/genyo/systems/modules/movement/GenyoVelocity.java index 2543a72..34f613b 100644 --- a/src/main/java/com/genyo/systems/modules/movement/GenyoVelocity.java +++ b/src/main/java/com/genyo/systems/modules/movement/GenyoVelocity.java @@ -28,6 +28,7 @@ import net.minecraft.sound.SoundEvents; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; import java.util.ArrayList; import java.util.List; @@ -198,7 +199,9 @@ public void onPacketReceive(PacketEvent.Receive event) { if (packet.getEntityId() != mc.player.getId()) return; - if (concealVelocity && packet.getVelocityX() == 0 && packet.getVelocityZ() == 0 && packet.getVelocityZ() == 0) { + Vec3d vel = ((AccessorEntityVelocityUpdateS2CPacket) packet).getVelocity(); + + if (concealVelocity && vel.x == 0 && vel.z == 0) { concealVelocity = false; return; } @@ -221,12 +224,11 @@ public void onPacketReceive(PacketEvent.Receive event) event.cancel(); return; } - ((AccessorEntityVelocityUpdateS2CPacket) packet).setVelocityX((int) (packet.getVelocityX() - * (horizontalConfig.get() / 100.0f))); - ((AccessorEntityVelocityUpdateS2CPacket) packet).setVelocityY((int) (packet.getVelocityY() - * (verticalConfig.get() / 100.0f))); - ((AccessorEntityVelocityUpdateS2CPacket) packet).setVelocityZ((int) (packet.getVelocityZ() - * (horizontalConfig.get() / 100.0f))); + ((AccessorEntityVelocityUpdateS2CPacket) packet).setVelocity(new Vec3d( + vel.x * (horizontalConfig.get() / 100.0f), + vel.y * (verticalConfig.get() / 100.0f), + vel.z * (horizontalConfig.get() / 100.0f) + )); } case GRIM -> { @@ -270,7 +272,6 @@ else if (event.packet instanceof ExplosionS2CPacket packet && explosionConfig.ge if (event.isCancelled()) { - // Dumb fix bc canceling explosion velocity removes explosion handling in 1.19 mc.executeSync(() -> ((AccessorClientWorld) mc.world).hookPlaySound(packet.center().getX(), packet.center().getY(), packet.center().getZ(), SoundEvents.ENTITY_GENERIC_EXPLODE.value(), SoundCategory.BLOCKS, 4.0f, (1.0f + (RANDOM.nextFloat() - RANDOM.nextFloat()) * 0.2f) * 0.7f, false, RANDOM.nextLong())); @@ -341,7 +342,7 @@ else if (packet1 instanceof EntityVelocityUpdateS2CPacket packet2 && knockbackCo if (!isPhased() && (!wallsTrappedConfig.get() || !isWallsTrapped())) { allowedBundle.add(packet1); - return; + continue; // was "return" — bug fix } if (wallsAirConfig.get() && !Managers.POSITION.isOnGround()) @@ -361,12 +362,12 @@ else if (packet1 instanceof EntityVelocityUpdateS2CPacket packet2 && knockbackCo } else { - ((AccessorEntityVelocityUpdateS2CPacket) packet2).setVelocityX((int) (packet2.getVelocityX() - * (horizontalConfig.get() / 100.0f))); - ((AccessorEntityVelocityUpdateS2CPacket) packet2).setVelocityY((int) (packet2.getVelocityY() - * (verticalConfig.get() / 100.0f))); - ((AccessorEntityVelocityUpdateS2CPacket) packet2).setVelocityZ((int) (packet2.getVelocityZ() - * (horizontalConfig.get() / 100.0f))); + Vec3d vel2 = ((AccessorEntityVelocityUpdateS2CPacket) packet2).getVelocity(); + ((AccessorEntityVelocityUpdateS2CPacket) packet2).setVelocity(new Vec3d( + vel2.x * (horizontalConfig.get() / 100.0f), + vel2.y * (verticalConfig.get() / 100.0f), + vel2.z * (horizontalConfig.get() / 100.0f) + )); } } case GRIM -> @@ -402,7 +403,6 @@ else if (event.packet instanceof EntityDamageS2CPacket packet { Managers.NETWORK.sendPacket(new PlayerMoveC2SPacket.OnGroundOnly(false, mc.player.horizontalCollision)); Managers.NETWORK.sendPacket(new PlayerMoveC2SPacket.OnGroundOnly(true, mc.player.horizontalCollision)); - // Managers.NETWORK.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(mc.player.getX(), mc.player.getY(), mc.player.getZ(), mc.player.isOnGround())); } else if (event.packet instanceof EntityStatusS2CPacket packet @@ -415,7 +415,6 @@ else if (event.packet instanceof EntityStatusS2CPacket packet } } } - @EventHandler public void onPlayerTick(PlayerTickEvent event) { diff --git a/src/main/java/com/genyo/systems/modules/movement/TsunodaBlinker.java b/src/main/java/com/genyo/systems/modules/movement/TsunodaBlinker.java index 6804f07..5406964 100644 --- a/src/main/java/com/genyo/systems/modules/movement/TsunodaBlinker.java +++ b/src/main/java/com/genyo/systems/modules/movement/TsunodaBlinker.java @@ -66,7 +66,7 @@ public void onActivate() { if (mc.player != null && render.get()) { - serverModel = new FakePlayerEntity(mc.player, mc.player.getGameProfile().getName(), 20, true); + serverModel = new FakePlayerEntity(mc.player, mc.player.getGameProfile().name(), 20, true); serverModel.spawn(); serverModel.setUuid(mc.player.getUuid()); } diff --git a/src/main/java/com/genyo/systems/modules/visual/AngelSexHulkenberg.java b/src/main/java/com/genyo/systems/modules/visual/AngelSexHulkenberg.java deleted file mode 100644 index 1e7fc5e..0000000 --- a/src/main/java/com/genyo/systems/modules/visual/AngelSexHulkenberg.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.genyo.systems.modules.visual; - -import com.genyo.Genyo; -import com.genyo.events.TotemPopEvent; -import com.genyo.mixin.entity.IEntity; -import com.genyo.systems.modules.GenyoModule; -import com.genyo.render.Render2DEngine; -import com.genyo.render.Render3DEngine; -import com.genyo.systems.enemies.Enemies; -import com.genyo.utils.math.MathUtil; -import com.mojang.authlib.GameProfile; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import meteordevelopment.meteorclient.events.render.Render3DEvent; -import meteordevelopment.meteorclient.events.world.TickEvent; -import meteordevelopment.meteorclient.settings.*; -import meteordevelopment.meteorclient.utils.render.color.Color; -import meteordevelopment.meteorclient.utils.render.color.SettingColor; -import meteordevelopment.orbit.EventHandler; -import net.minecraft.client.gl.ShaderProgramKeys; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.render.*; -import net.minecraft.client.render.entity.PlayerEntityRenderer; -import net.minecraft.client.render.entity.state.PlayerEntityRenderState; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.RotationAxis; -import org.jetbrains.annotations.NotNull; - -import java.util.concurrent.CopyOnWriteArrayList; - -public final class AngelSexHulkenberg extends GenyoModule { - - public AngelSexHulkenberg() { - super(Genyo.VISUAL, "angel-sex-hulkenberg", "jön a verstappen, nekiütközött a verstappen, kiesik a verstappen"); - } - - private final SettingGroup sgGeneral = settings.getDefaultGroup(); - private final SettingGroup sgRender = settings.createGroup("Render"); - private final SettingGroup sgSpeed = settings.createGroup("Speed"); - - private final Setting focusEnemy = sgGeneral.add(new BoolSetting.Builder() - .name("Focus Enemies") - .description("enemyknél csinálja csak") - .defaultValue(false) - .build() - ); - - // Render - - private final Setting mode = sgRender.add(new EnumSetting.Builder() - .name("Mode") - .description("Ki a faszom az a Hulkenberg??????????") - .defaultValue(Mode.Textured) - .build() - ); - - private final Setting rotate180 = sgRender.add(new BoolSetting.Builder() - .name("Rotate Y 180") - .description("fejjel lefelé mert igen") - .defaultValue(false) - .build() - ); - - private final Setting secondLayer = sgRender.add(new BoolSetting.Builder() - .name("Second Layer") - .description("kiyártam a kettedik osztájt") - .defaultValue(true) - .build() - ); - - private final Setting color = sgRender.add(new ColorSetting.Builder() - .name("Color") - .description("színcápa színcápa mondj egy színt") - .defaultValue(new Color(53, 46, 46, 255)) - .build() - ); - - // Speed - - private final Setting ySpeed = sgSpeed.add(new IntSetting.Builder() - .name("Y Speed") - .description("y show speed") - .defaultValue(2) - .min(0) - .max(6) - .build() - ); - - private final Setting aSpeed = sgSpeed.add(new IntSetting.Builder() - .name("Alpha Speed") - .description("alpha-i show speed") - .defaultValue(5) - .min(1) - .max(100) - .build() - ); - - private final Setting rotSpeed = sgSpeed.add(new DoubleSetting.Builder() - .name("Rotation Speed") - .description("rotációs kapa") - .defaultValue(1d) - .min(0d) - .max(6d) - .build() - ); - - private final CopyOnWriteArrayList popList = new CopyOnWriteArrayList<>(); - - private enum Mode { - Simple, Textured - } - - @EventHandler - public void onTick(TickEvent.Pre event) { - popList.forEach(person -> person.update(popList)); - } - - @EventHandler - public void onRender(Render3DEvent event) { - MatrixStack stack = event.matrices; - - RenderSystem.enableBlend(); - RenderSystem.disableDepthTest(); - - if (mode.get().equals(Mode.Simple)) RenderSystem.defaultBlendFunc(); - else RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE); - - popList.forEach(person -> renderEntity(stack, person.player, person.getTexture(), person.getAlpha())); - - RenderSystem.enableDepthTest(); - RenderSystem.disableBlend(); - - popList.forEach(person -> renderEntity(stack, person.player, person.getTexture(), person.getAlpha())); - } - - @EventHandler - @SuppressWarnings("unused") - private void onTotemPop(@NotNull TotemPopEvent e) { - if (e.entity.equals(mc.player) || mc.world == null) return; - //if (mc.world == null) return; //-------- for testing - if (mc.getServer() == null) return; - - if (focusEnemy.get()) if (!(Enemies.get().isEnemy(e.entity))) return; - - AbstractClientPlayerEntity entity = new AbstractClientPlayerEntity(mc.world, new GameProfile(e.entity.getUuid(), e.entity.getName().getString())) { - @Override public boolean isSpectator() {return false;} - @Override public boolean isCreative() {return false;} - }; - - entity.copyPositionAndRotation(e.entity); - entity.bodyYaw = e.entity.bodyYaw; - entity.headYaw = e.entity.headYaw; - entity.handSwingProgress = e.entity.handSwingProgress; - entity.handSwingTicks = e.entity.handSwingTicks; - entity.setSneaking(e.entity.isSneaking()); - entity.limbAnimator.setSpeed(e.entity.limbAnimator.getSpeed()); - - Identifier skin = ((AbstractClientPlayerEntity) e.entity).getSkinTextures().texture(); - - popList.add(new Person(entity, skin, mc.getServer().getWorld(entity.getWorld().getRegistryKey()))); - } - - private void renderEntity(@NotNull MatrixStack matrices, @NotNull LivingEntity entity, Identifier texture, int alpha) { - PlayerEntityRenderer entityRenderer = (PlayerEntityRenderer) mc.getEntityRenderDispatcher().getRenderer((AbstractClientPlayerEntity) entity); - PlayerEntityRenderState renderState = entityRenderer.createRenderState(); - - renderState.leftPantsLegVisible = secondLayer.get(); - renderState.rightPantsLegVisible = secondLayer.get(); - renderState.leftSleeveVisible = secondLayer.get(); - renderState.rightSleeveVisible = secondLayer.get(); - renderState.jacketVisible = secondLayer.get(); - renderState.hatVisible = secondLayer.get(); - - double x = entity.getX() - mc.getEntityRenderDispatcher().camera.getPos().getX(); - double y = entity.getY() - mc.getEntityRenderDispatcher().camera.getPos().getY(); - double z = entity.getZ() - mc.getEntityRenderDispatcher().camera.getPos().getZ(); - ((IEntity) entity).setPos(entity.getPos().add(0, (double) ySpeed.get() / 50., 0)); - - matrices.push(); - matrices.translate((float) x, (float) y, (float) z); - - float yRotYaw = ((alpha / 255f) * 360f * rotSpeed.get().floatValue()); - yRotYaw = yRotYaw == 0 ? 0 : Render2DEngine.interpolateFloat(yRotYaw, yRotYaw - (((aSpeed.get() / 255f) * 360f * rotSpeed.get().floatValue())), Render3DEngine.getTickDelta()); - - matrices.multiply(RotationAxis.POSITIVE_Y.rotation(MathUtil.rad(180 - entity.bodyYaw + yRotYaw))); - prepareScale(matrices, rotate180.get()); - - float limbSpeed = Math.min(entity.limbAnimator.getSpeed(), 1f); - - entityRenderer.updateRenderState((AbstractClientPlayerEntity) entity, renderState, limbSpeed); - renderState.limbFrequency = limbSpeed; - renderState.age = entity.age; - renderState.yawDegrees = entity.headYaw - entity.bodyYaw; - renderState.pitch = entity.getPitch(); - - BufferBuilder buffer; - if (mode.get().equals(Mode.Textured)) { - RenderSystem.setShaderTexture(0, texture); - RenderSystem.setShader(ShaderProgramKeys.POSITION_TEX); - buffer = Tessellator.getInstance().begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE); - } else { - RenderSystem.setShader(ShaderProgramKeys.POSITION); - buffer = Tessellator.getInstance().begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION); - } - - RenderSystem.setShaderColor(color.get().r, color.get().g, color.get().b, alpha / 255f); - - entityRenderer.render(renderState, matrices, mc.getBufferBuilders().getEntityVertexConsumers(), 1); - - Render2DEngine.endBuilding(buffer); - RenderSystem.setShaderColor(1f, 1f, 1f, 1f); - matrices.pop(); - } - - private static void prepareScale(@NotNull MatrixStack matrixStack, boolean rotate) { - if (rotate) matrixStack.scale(-1.0F, -1.0F, 1.0F); - else matrixStack.scale(-1.0F, 1.0F, 1.0F); - - matrixStack.scale(1.6f, 1.8f, 1.6f); - matrixStack.translate(0.0F, -1.501F, 0.0F); - } - - private class Person { - private final AbstractClientPlayerEntity player; - private final Identifier texture; - private int alpha; - private final ServerWorld world; - - public Person(AbstractClientPlayerEntity player, Identifier texture, ServerWorld world) { - this.player = player; - this.world = world; - this.texture = texture; - alpha = color.get().a; - } - - public void update(CopyOnWriteArrayList arrayList) { - if (alpha <= 0) { - arrayList.remove(this); - player.kill(world); - player.remove(Entity.RemovalReason.KILLED); - player.onRemoved(); - return; - } - alpha -= aSpeed.get(); - } - - public int getAlpha() { - return MathUtil.clamp(alpha, 0, 255); - } - - public Identifier getTexture() { - return texture; - } - } -} diff --git a/src/main/java/com/genyo/systems/modules/visual/GenyoCapes.java b/src/main/java/com/genyo/systems/modules/visual/GenyoCapes.java index 99cea24..1f6029a 100644 --- a/src/main/java/com/genyo/systems/modules/visual/GenyoCapes.java +++ b/src/main/java/com/genyo/systems/modules/visual/GenyoCapes.java @@ -2,19 +2,43 @@ import com.genyo.Genyo; import com.genyo.systems.modules.GenyoModule; +import meteordevelopment.meteorclient.settings.BoolSetting; +import meteordevelopment.meteorclient.settings.Setting; +import meteordevelopment.meteorclient.settings.SettingGroup; import net.minecraft.util.Identifier; +import java.util.Set; + public class GenyoCapes extends GenyoModule { + private static final Set DEV_NAMES = Set.of( + "Awakeyv", + "wuritz", + "Barnika18" + ); + + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + + public final Setting everyoneConfig = sgGeneral.add(new BoolSetting.Builder() + .name("Everyone") + .description("Apply Genyo cape to all players.") + .defaultValue(false) + .build() + ); + private final Identifier capeTexture; + private final Identifier devCapeTexture; public GenyoCapes() { super(Genyo.VISUAL, "genyo-capes", "The thing"); this.capeTexture = Identifier.of(Genyo.MOD_ID, "textures/cape.png"); + this.devCapeTexture = Identifier.of(Genyo.MOD_ID, "textures/cape_dev.png"); } - public Identifier getCapeTexture() { - return capeTexture; - } + public Identifier getCapeTexture() {return capeTexture;} + + public Identifier getDevCapeTexture() {return devCapeTexture;} + + public boolean isDev(String username) {return DEV_NAMES.contains(username);} } diff --git a/src/main/java/com/genyo/systems/modules/visual/GenyoNametags.java b/src/main/java/com/genyo/systems/modules/visual/GenyoNametags.java index 87ecee4..d47728d 100644 --- a/src/main/java/com/genyo/systems/modules/visual/GenyoNametags.java +++ b/src/main/java/com/genyo/systems/modules/visual/GenyoNametags.java @@ -17,7 +17,7 @@ import meteordevelopment.meteorclient.systems.friends.Friends; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Modules; -import meteordevelopment.meteorclient.systems.modules.misc.NameProtect; +import meteordevelopment.meteorclient.systems.modules.player.NameProtect; import meteordevelopment.meteorclient.systems.modules.render.Freecam; import meteordevelopment.meteorclient.systems.modules.render.Nametags; import meteordevelopment.meteorclient.utils.Utils; @@ -339,7 +339,7 @@ private void onTick(TickEvent.Post event) { boolean freecamNotActive = !Modules.get().isActive(Freecam.class); boolean notThirdPerson = mc.options.getPerspective().isFirstPerson(); - Vec3d cameraPos = mc.gameRenderer.getCamera().getPos(); + Vec3d cameraPos = mc.gameRenderer.getCamera().getCameraPos(); for (Entity entity : mc.world.getEntities()) { EntityType type = entity.getType(); @@ -479,7 +479,7 @@ private void renderNametagPlayer(Render2DEvent event, PlayerEntity player, boole double width = nameWidth; - boolean renderPlayerDistance = player != mc.cameraEntity || Modules.get().isActive(Freecam.class); + boolean renderPlayerDistance = player != mc.getCameraEntity() || Modules.get().isActive(Freecam.class); if (displayHealth.get()) width += healthWidth; if (displayGameMode.get()) width += gmWidth; @@ -735,10 +735,10 @@ private void renderTntNametag(String fuseText, boolean shadow) { private ItemStack getItem(PlayerEntity entity, int index) { return switch (index) { case 0 -> entity.getMainHandStack(); - case 1 -> entity.getInventory().armor.get(3); - case 2 -> entity.getInventory().armor.get(2); - case 3 -> entity.getInventory().armor.get(1); - case 4 -> entity.getInventory().armor.get(0); + case 1 -> entity.getInventory().getStack(39); // HEAD + case 2 -> entity.getInventory().getStack(38); // CHEST + case 3 -> entity.getInventory().getStack(37); // LEGS + case 4 -> entity.getInventory().getStack(36); // FEET case 5 -> entity.getOffHandStack(); default -> ItemStack.EMPTY; }; @@ -747,7 +747,7 @@ private ItemStack getItem(PlayerEntity entity, int index) { private void drawBg(double x, double y, double width, double height) { Renderer2D.COLOR.begin(); Renderer2D.COLOR.quad(x - 1, y - 1, width + 2, height + 2, background.get()); - Renderer2D.COLOR.render(null); + Renderer2D.COLOR.render(); } public enum Position { diff --git a/src/main/java/com/genyo/systems/modules/visual/Parkinsons.java b/src/main/java/com/genyo/systems/modules/visual/Parkinsons.java index 73edfe3..26139ab 100644 --- a/src/main/java/com/genyo/systems/modules/visual/Parkinsons.java +++ b/src/main/java/com/genyo/systems/modules/visual/Parkinsons.java @@ -23,7 +23,7 @@ public Parkinsons() { public void onActivate() { shouldFreeze = true; - storedPos = mc.player.getPos(); + storedPos = mc.player.getEntityPos(); storedYaw = mc.player.getYaw(); storedPitch = mc.player.getPitch(); @@ -41,7 +41,7 @@ public void onActivate() { @EventHandler public void onTick(TickEvent.Pre event) { - Entity camera = mc.cameraEntity; + Entity camera = mc.getCameraEntity(); Vec3d forward = Vec3d.fromPolar(0, camera.getYaw()).normalize(); Vec3d right = new Vec3d(-forward.z, 0, forward.x).normalize(); @@ -56,7 +56,7 @@ public void onTick(TickEvent.Pre event) { if (velocity.lengthSquared() > 0) { velocity = velocity.normalize().multiply(1); - Vec3d pos = camera.getPos(); + Vec3d pos = camera.getEntityPos(); camera.setPos(pos.x + velocity.x, pos.y + velocity.y, pos.z + velocity.z); } diff --git a/src/main/java/com/genyo/systems/modules/visual/PenisESP.java b/src/main/java/com/genyo/systems/modules/visual/PenisESP.java index eeef202..db6e22a 100644 --- a/src/main/java/com/genyo/systems/modules/visual/PenisESP.java +++ b/src/main/java/com/genyo/systems/modules/visual/PenisESP.java @@ -111,9 +111,9 @@ public void onRender3D(Render3DEvent event) { } public Vec3d getBase(Entity entity, float tickDelta) { - double x = entity.prevX + ((entity.getX() - entity.prevX) * tickDelta); - double y = entity.prevY + ((entity.getY() - entity.prevY) * tickDelta); - double z = entity.prevZ + ((entity.getZ() - entity.prevZ) * tickDelta); + double x = entity.lastX + ((entity.getX() - entity.lastX) * tickDelta); + double y = entity.lastY + ((entity.getY() - entity.lastY) * tickDelta); + double z = entity.lastZ + ((entity.getZ() - entity.lastZ) * tickDelta); return new Vec3d(x, y, z); } diff --git a/src/main/java/com/genyo/systems/modules/world/AutoMineV2.java b/src/main/java/com/genyo/systems/modules/world/AutoMineV2.java deleted file mode 100644 index ec8b196..0000000 --- a/src/main/java/com/genyo/systems/modules/world/AutoMineV2.java +++ /dev/null @@ -1,334 +0,0 @@ -package com.genyo.systems.modules.world; - -import com.genyo.Genyo; -import com.genyo.managers.player.InteractionManager; -import com.genyo.systems.modules.PlacerModule; -import com.genyo.utils.math.timer.CacheTimer; -import com.genyo.utils.math.timer.Timer; -import com.genyo.utils.player.Rotation; -import com.genyo.utils.player.RotationUtil; -import meteordevelopment.meteorclient.events.world.TickEvent; -import meteordevelopment.meteorclient.settings.*; -import meteordevelopment.meteorclient.utils.entity.SortPriority; -import meteordevelopment.meteorclient.utils.entity.TargetUtils; -import meteordevelopment.meteorclient.utils.render.color.SettingColor; -import meteordevelopment.meteorclient.utils.world.BlockUtils; -import meteordevelopment.orbit.EventHandler; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.math.BlockPos; - -import java.util.*; - -public class AutoMineV2 extends PlacerModule { - - public AutoMineV2() { - super(Genyo.WORLD, "auto-mine-v2", "Hopefully better automine"); - } - - /*private final SettingGroup sgGeneral = settings.getDefaultGroup(); - private final SettingGroup sgRender = settings.createGroup("Render"); - - private final Setting delay = sgGeneral.add(new IntSetting.Builder() - .name("delay") - .description("MS delay") - .min(0).defaultValue(0).max(1000) - .sliderRange(0, 1000) - .onChanged((asd) -> {}) - .build() - ); - - private final Setting minDmg = sgGeneral.add(new IntSetting.Builder() - .name("minimum-damage") - .description("-") - .min(0).defaultValue(7).max(36) - .sliderRange(0, 36) - .build() - ); - - private final Setting targetRange = sgGeneral.add(new DoubleSetting.Builder() - .name("target-range") - .description("") - .min(1d).defaultValue(5d).max(10d) - .sliderRange(1d, 10d) - .build() - ); - - private final Setting range = sgGeneral.add(new IntSetting.Builder() - .name("range") - .description("-") - .min(3).defaultValue(6).max(6) - .sliderRange(3, 6) - .build() - ); - - private final Setting blocksPerTick = sgGeneral.add(new IntSetting.Builder() - .name("blocks-per-tick") - .description("-") - .min(1).defaultValue(10).max(10) - .sliderRange(1, 10) - .build() - ); - - private final Setting rotate = sgGeneral.add(new BoolSetting.Builder() - .name("rotate") - .description("-") - .defaultValue(false) - .build() - ); - - // render - - private final Setting render = sgRender.add(new BoolSetting.Builder() - .name("render") - .description("render") - .defaultValue(true) - .build() - ); - - private final Setting fill = sgRender.add(new ColorSetting.Builder() - .name("fill-color") - .description("Fill Color") - .defaultValue(new SettingColor(255, 0, 0, 25)) - .visible(render::get) - .build() - ); - - private final Setting line = sgRender.add(new ColorSetting.Builder() - .name("line-color") - .description("Line Color") - .defaultValue(new SettingColor(255, 0, 0, 255)) - .visible(render::get) - .build() - ); - - private final Setting fadeTime = sgRender.add(new IntSetting.Builder() - .name("fade-time") - .description("Fade Time in milliseconds") - .min(0).defaultValue(200).max(1000) - .sliderRange(0, 1000) - .build() - ); - - - private Timer timer = new CacheTimer(); - public Map renderPositions = new HashMap<>(); - - private Entity target; - private List toPlace = new ArrayList<>(); - - public Map placed = new HashMap<>(); - - double startY = 0; - - @EventHandler - public void onTick(TickEvent.Pre event) { - if (mc.player == null || mc.world == null || mc.interactionManager == null) return; - - if (getSlot() == -1) { - return; - } - - for (Map.Entry entry : placed.entrySet()) { - BlockPos pos = entry.getKey(); - long time = entry.getValue(); - - if (System.currentTimeMillis() - time > 200) { - placed.remove(pos); - } - } - - toPlace.clear(); - int blocksInTick = 0; - - target = TargetUtils.getPlayerTarget(targetRange.get(), SortPriority.LowestDistance); - - if (target != null) { - - BlockPos targetPos = getBestCrystalPlacePos((PlayerEntity) target); - - if (mc.world.getBlockState(targetPos).isReplaceable()) { - placeLabel: - if (timer.passed(delay.get())) { - - if (blocksInTick >= blocksPerTick.get()) break placeLabel; - - if (toPlace.contains(targetPos)) break placeLabel; - - if (placed.containsKey(targetPos)) { - - if (CrystalManager.INSTANCE.isRecentlyBlocked(targetPos)) - placed.remove(targetPos); - else if (System.currentTimeMillis() - placed.get(targetPos) < 60) - break placeLabel; - } - - if (blocksInTick == 0 && rotate.get()) - Rotation.get().setRotationSilentSync(); - - toPlace.add(targetPos); - blocksInTick++; - timer.reset(); - } - } - } - - doPlace(); - } - - public BlockPos getBestCrystalPlacePos(PlayerEntity player) { - BlockPos bestPos = null; - double bestDMG = 0.5D; - - final List sphere = BlockUtils.sphere(range.getValue().doubleValue() + 1.0f, mc.player.getBlockPos(), true, false); - Set keySet = new HashSet<>(Set.copyOf(placed.keySet())); - keySet.addAll(toPlace); - - for (BlockPos pos : sphere) { - - BlockPos basePos = pos.down(); - - //check if valid place spot too cuz if theres an obby already there not tryna spam obby like a retard - if (!CrystalUtil.canPlaceCrystal(basePos, CatAura.INSTANCE.onePointTwelve.getValue()) && !BlockUtils.isReplaceable(basePos)) - continue; - - if (basePos.getY() >= player.getBlockPos().getY()) - continue; - - if(!CrystalUtil.canPlaceCrystalAir(basePos)) continue; - - if(BlockUtils.isBlockedOff(basePos) || BlockUtils.isBlockedOff(pos)) continue; - - if(BlockUtils.isReplaceable(basePos)) { - if (!BlockUtils.canPlaceBlock(basePos, strictDirection.getValue(), keySet)) continue; - } - - double distance = mc.player.getEyePos().squaredDistanceTo(new Vec3d(basePos.getX() + 0.5, basePos.getY() + 0.5, basePos.getZ() + 0.5)); - if (distance > MathUtil.square(range.getValue().doubleValue())) - continue; - - double dmg = CrystalUtil.calculateDamage(player, pos.toCenterPos(), CatAura.INSTANCE.terrain.getValue(), CatAura.INSTANCE.getMiningIgnore()); - if (dmg < minDmg.getValue().doubleValue()) { - continue; - } - - if (dmg > bestDMG) { - bestPos = basePos; - bestDMG = dmg; - } - - - } - return bestPos; - } - - @SubscribeEvent - public void onPlayerUpdate(TickEvent.PlayerTickEvent.Post event) { - - if (NullUtils.nullCheck()) return; - - if (!AntiCheat.INSTANCE.protocol.getValue()) - doPlace(); - } - - - @SubscribeEvent - public void onCollision(CollisionBoxEvent event) { - if (NullUtils.nullCheck()) return; - - - if (placed.containsKey(event.getPos())) { - - event.setCancelled(true); - event.setVoxelShape(VoxelShapes.cuboid(new Box(0, 0, 0, 1.0, 1.0, 1.0))); - } - } - - - @Override - public void onEnable() { - super.onEnable(); - if (NullUtils.nullCheck()) return; - - startY = mc.player.getY(); - - placed.clear(); - } - - - @Override - public void onDisable() { - super.onDisable(); - if (NullUtils.nullCheck()) return; - - if (PriorityManager.INSTANCE.isUsageLocked() && PriorityManager.INSTANCE.usageLockCause.equals("AutoPlacer")) - PriorityManager.INSTANCE.unlockUsageLock(); - - placed.clear(); - - } - - boolean rotateFlag = false; - - - public void doPlace() { - if (NullUtils.nullCheck()) return; - - int blockSlot = getSlot(); - - int oldSlot = mc.player.getInventory().selectedSlot; - boolean switched = false; - for (BlockPos pos : toPlace) { - - if (blockSlot != mc.player.getInventory().selectedSlot) { - InventoryUtils.switchToSlot(blockSlot); - switched = true; - } - - placed.put(pos, System.currentTimeMillis()); - - - if (rotate.getValue() && AntiCheat.INSTANCE.protocol.getValue()) - RotationUtils.doSilentRotate(pos, strictDirection.getValue()); - - BlockUtils.placeBlock(pos, BlockUtils.getPlaceableSide(pos, strictDirection.getValue(), placed.keySet()), !mc.player.getMainHandStack().getItem().equals(Items.ENDER_CHEST)); - - - if (render.getValue()) - renderPositions.put(pos, System.currentTimeMillis()); - - } - if (switched) { - InventoryUtils.switchToSlot(oldSlot); - } - if ((!toPlace.isEmpty() && AntiCheat.INSTANCE.protocol.getValue() && rotate.getValue()) || rotateFlag) { - RotationUtils.silentSync(); - } - toPlace.clear(); - - } - - - int getSlot() { - return InventoryUtils.getHotbarItemSlot(Items.OBSIDIAN); - } - - - @SubscribeEvent - public void onPacket(PacketEvent.Receive event) { - if (NullUtils.nullCheck()) return; - - if (event.getPacket() instanceof BlockUpdateS2CPacket packet) { - final BlockPos targetPos = packet.getPos(); - if (placed.containsKey(targetPos)) { - placed.remove(targetPos); - } - } - } - - @Override - public String getDescription() { - return "AutoPlacer: places obby in places to place crystals"; - }*/ - -} diff --git a/src/main/java/com/genyo/systems/modules/world/GenyoAutoMine.java b/src/main/java/com/genyo/systems/modules/world/GenyoAutoMine.java index 285cad8..7a5e8a8 100644 --- a/src/main/java/com/genyo/systems/modules/world/GenyoAutoMine.java +++ b/src/main/java/com/genyo/systems/modules/world/GenyoAutoMine.java @@ -1,4 +1,5 @@ -package com.genyo.systems.modules.world; + + package com.genyo.systems.modules.world; import com.genyo.Genyo; import com.genyo.events.AttackBlockEvent; @@ -21,7 +22,7 @@ import meteordevelopment.meteorclient.renderer.Renderer3D; import meteordevelopment.meteorclient.renderer.ShapeMode; import meteordevelopment.meteorclient.settings.*; -import meteordevelopment.meteorclient.systems.modules.Modules; + import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.render.color.SettingColor; import meteordevelopment.orbit.EventHandler; @@ -38,7 +39,7 @@ import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; import net.minecraft.util.Hand; import net.minecraft.util.math.*; -import net.minecraft.util.shape.VoxelShape; + import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/com/genyo/systems/modules/world/GenyoAutoMineV2.java b/src/main/java/com/genyo/systems/modules/world/GenyoAutoMineV2.java new file mode 100644 index 0000000..5cbe1c2 --- /dev/null +++ b/src/main/java/com/genyo/systems/modules/world/GenyoAutoMineV2.java @@ -0,0 +1,1274 @@ +package com.genyo.systems.modules.world; + +import com.genyo.Genyo; +import com.genyo.events.AttackBlockEvent; +import com.genyo.managers.Managers; +import com.genyo.systems.modules.GenyoModule; +import com.genyo.systems.modules.combat.GenyoAutoCrystal; +import com.genyo.render.animation.Animation; +import com.genyo.systems.settings.FloatSetting; +import com.genyo.utils.GEntityUtils; +import com.genyo.utils.math.GPositionUtils; +import com.genyo.utils.math.MathUtil; +import com.genyo.utils.math.timer.CacheTimer; +import com.genyo.utils.math.timer.Timer; +import com.genyo.utils.player.RotationUtil; +import com.genyo.utils.render.ColorUtil; +import com.genyo.utils.world.BlastResistantBlocks; +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.render.Render3DEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.renderer.Renderer3D; +import meteordevelopment.meteorclient.renderer.ShapeMode; +import meteordevelopment.meteorclient.settings.*; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.utils.render.color.Color; +import meteordevelopment.meteorclient.utils.render.color.SettingColor; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.block.BlockState; +import net.minecraft.block.ShapeContext; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.EntityPose; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; +import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket; +import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; +import net.minecraft.util.Hand; +import net.minecraft.util.math.*; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +public class GenyoAutoMineV2 extends GenyoModule { + + public GenyoAutoMineV2() { + super(Genyo.WORLD, "Genyo AutoMineV2", "fasz"); + } + + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final SettingGroup sgSelection = settings.createGroup("Selection"); + private final SettingGroup sgRender = settings.createGroup("Render"); + + private final Setting multitask = sgGeneral.add(new BoolSetting.Builder() + .name("Allow Multitask") + .description("Allows actions while using items") + .defaultValue(true) + .build() + ); + + private final Setting auto = sgSelection.add(new BoolSetting.Builder() + .name("Auto") + .description("Automatically mines nearby players feet") + .defaultValue(false) + .build() + ); + + private final Setting selection = sgSelection.add(new EnumSetting.Builder() + .name("Selection") + .description("The selection of blocks mine") + .visible(auto::get) + .defaultValue(Selection.ALL) + .build() + ); + + private final Setting avoidSelf = sgSelection.add(new BoolSetting.Builder() + .name("Avoid Self") + .description("Avoids mining blocks in your surround") + .defaultValue(false) + .visible(auto::get) + .build() + ); + + private final Setting> whitelist = sgSelection.add(new BlockListSetting.Builder() + .name("Block Whitelist") + .description("Valid block whitelist") + .defaultValue(Blocks.OBSIDIAN, Blocks.ENDER_CHEST) + .build() + ); + + private final Setting> blacklist = sgSelection.add(new BlockListSetting.Builder() + .name("Block Blacklist") + .description("Valid block blacklist") + .defaultValue(Blocks.SHULKER_BOX) + .build() + ); + + private final Setting enemyRange = sgSelection.add(new FloatSetting.Builder() + .name("Enemy Range") + .description("Only mines on visible faces") + .defaultValue(5.0f) + .min(1.0f) + .max(10.0f) + .visible(auto::get) + .build() + ); + + private final Setting strictDirection = sgSelection.add(new BoolSetting.Builder() + .name("Strict Direction") + .description("Only mines on visible faces") + .visible(auto::get) + .defaultValue(false) + .build() + ); + + private final Setting antiCrawl = sgSelection.add(new BoolSetting.Builder() + .name("Anti Crawl") + .description("Attempts to stop player from crawling") + .defaultValue(false) + .build() + ); + + private final Setting head = sgSelection.add(new BoolSetting.Builder() + .name("Target Body") + .description("Attempts to mine players face blocks") + .defaultValue(false) + .visible(auto::get) + .build() + ); + + private final Setting aboveHead = sgSelection.add(new BoolSetting.Builder() + .name("Target Head") + .description("Attempts to mine above players head") + .defaultValue(false) + .visible(auto::get) + .build() + ); + + private final Setting doubleBreak = sgGeneral.add(new BoolSetting.Builder() + .name("Double Break") + .description("Allows you to mine two blocks at once") + .defaultValue(true) + .build() + ); + + private final Setting mineTicks = sgGeneral.add(new IntSetting.Builder() + .name("Mining Ticks") + .description("The max number of ticks to hold a pickaxe for the packet mine") + .min(5) + .max(60) + .defaultValue(20) + .visible(doubleBreak::get) + .build() + ); + + private final Setting remine = sgGeneral.add(new EnumSetting.Builder() + .name("Remine") + .description("Remines already mined blocks") + .defaultValue(RemineMode.INSTANT) + .build() + ); + + private final Setting packetInstant = sgGeneral.add(new BoolSetting.Builder() + .name("Fast") + .description("Instant mines on packet") + .defaultValue(true) + .visible(() -> remine.get() == RemineMode.INSTANT) + .build() + ); + + private final Setting range = sgGeneral.add(new FloatSetting.Builder() + .name("Range") + .description("The range to mine blocks") + .min(0.1f) + .defaultValue(6.0f) + .max(6.0f) + .build() + ); + + private final Setting speed = sgGeneral.add(new FloatSetting.Builder() + .name("Speed") + .description("The speed to mine blocks (idk what the fuck this is)") + .min(0.1f) + .defaultValue(1.0f) + .max(1.0f) + .build() + ); + + private final Setting swap = sgGeneral.add(new EnumSetting.Builder() + .name("Auto Swap") + .description("Swaps to the best tool once the mining is complete") + .defaultValue(Swap.SILENT) + .build() + ); + + private final Setting swapBefore = sgGeneral.add(new BoolSetting.Builder() + .name("Swap Before") + .description("Swaps before fully done mining") + .defaultValue(false) + .visible(() -> swap.get() != Swap.OFF) + .build() + ); + + private final Setting rotate = sgGeneral.add(new BoolSetting.Builder() + .name("Rotate") + .description("yes") + .defaultValue(true) + .build() + ); + + private final Setting switchReset = sgGeneral.add(new BoolSetting.Builder() + .name("Switch Reset") + .description("Resets mining after switching items") + .defaultValue(false) + .build() + ); + + private final Setting grim = sgGeneral.add(new BoolSetting.Builder() + .name("Grim") + .description("Uses grim block breaking speeds") + .defaultValue(false) + .build() + ); + + private final Setting grimNew = sgGeneral.add(new BoolSetting.Builder() + .name("Grim V3") + .description("Allows mining on new grim servers") + .defaultValue(false) + .visible(grim::get) + .build() + ); + + private final Setting anticheat = sgGeneral.add(new BoolSetting.Builder() + .name("Anti Cheat") + .description("grim anti cheat genyo fasz") + .defaultValue(false) + .build() + ); + + // Render + + private final Setting render = sgRender.add(new BoolSetting.Builder() + .name("Render") + .description("wa") + .defaultValue(true) + .build() + ); + + private final Setting mineColor = sgRender.add(new ColorSetting.Builder() + .name("Mine Color") + .description("The mine render color") + .defaultValue(new SettingColor(255, 0, 0, 255)) + .build() + ); + + private final Setting colorDone = sgRender.add(new ColorSetting.Builder() + .name("Done Color") + .description("The done render color") + .defaultValue(new SettingColor(0, 255, 0, 255)) + .build() + ); + + private final Setting fadeTime = sgRender.add(new IntSetting.Builder() + .name("Fade Time") + .description("Time to fade") + .min(0) + .defaultValue(250) + .max(1000) + .visible(() -> false) + .build() + ); + + private final Setting smoothColor = sgRender.add(new BoolSetting.Builder() + .name("Smooth Color") + .description("Interpolates from start to done color") + .defaultValue(false) + .build() + ); + + private PlayerEntity playerTarget; + private MineData packetMine, instantMine; + private boolean packetSwapBack; + private boolean manualOverride; + private final Timer remineTimer = new CacheTimer(); + + private boolean changedInstantMine; + private boolean waitForPacketMine; + private boolean packetMineStuck; + + private boolean antiCrawlOverride; + private int antiCrawlTicks; + + private final Queue autoMineQueue = new ArrayDeque<>(); + private int autoMineTickDelay; + + private MineAnimation packetMineAnim = new MineAnimation( + MineData.empty(), new Animation(true, 200)); + private MineAnimation instantMineAnim = new MineAnimation( + MineData.empty(), new Animation(true, 200)); + + @Override + public void onDeactivate() + { + autoMineQueue.clear(); + playerTarget = null; + packetMine = null; + if (instantMine != null) + { + abortMining(instantMine); + instantMine = null; + } + packetMineAnim = new MineAnimation(MineData.empty(), new Animation(true, 200)); + instantMineAnim = new MineAnimation(MineData.empty(), new Animation(true, 200)); + autoMineTickDelay = 0; + antiCrawlTicks = 0; + manualOverride = false; + antiCrawlOverride = false; + waitForPacketMine = false; + packetMineStuck = false; + if (packetSwapBack) + { + Managers.INVENTORY.syncToClient(); + packetSwapBack = false; + } + } + + @EventHandler + public void onTick(TickEvent.Pre event) + { + if (mc.player.isCreative() || mc.player.isSpectator()) + { + return; + } + + PlayerEntity currentTarget = getClosestPlayer(enemyRange.get()); + boolean targetChanged = playerTarget != null && playerTarget != currentTarget; + playerTarget = currentTarget; + + if (isInstantMineComplete()) + { + if (changedInstantMine) + { + changedInstantMine = false; + } + if (waitForPacketMine) + { + waitForPacketMine = false; + } + } + + autoMineTickDelay--; + antiCrawlTicks--; + + // Mining packet handling + if (packetMine != null && packetMine.getTicksMining() > mineTicks.get()) + { + packetMineStuck = true; + packetMineAnim.animation.setState(false); + if (packetSwapBack) + { + Managers.INVENTORY.syncToClient(); + packetSwapBack = false; + } + packetMine = null; + if (!isInstantMineComplete()) + { + waitForPacketMine = true; + } + } + + if (packetMine != null) + { + final float damageDelta = Modules.get().get(GenyoSpeedmine.class).calcBlockBreakingDelta( + packetMine.getState(), mc.world, packetMine.getPos()); + packetMine.addBlockDamage(damageDelta); + + int slot = packetMine.getBestSlot(); + float damageDone = packetMine.getBlockDamage() + (swapBefore.get() + || packetMineStuck ? damageDelta : 0.0f); + if (damageDone >= 1.0f && slot != -1 && !checkMultitask()) + { + Managers.INVENTORY.setSlot(slot); + packetSwapBack = true; + if (packetMineStuck) + { + packetMineStuck = false; + } + } + } + + if (packetSwapBack) + { + if (packetMine != null && canMine(packetMine.getState())) + { + packetMine.markAttemptedMine(); + } + else + { + Managers.INVENTORY.syncToClient(); + packetSwapBack = false; + packetMineAnim.animation.setState(false); + packetMine = null; + if (!isInstantMineComplete()) + { + waitForPacketMine = true; + } + } + } + + if (instantMine != null) + { + final double distance = mc.player.getEyePos().squaredDistanceTo(instantMine.getPos().toCenterPos()); + if (distance > MathUtil.squared(range.get()) + || instantMine.getTicksMining() > mineTicks.get()) + { + abortMining(instantMine); + instantMineAnim.animation.setState(false); + instantMine = null; + } + } + + if (instantMine != null) + { + final float damageDelta = Modules.get().get(GenyoSpeedmine.class).calcBlockBreakingDelta( + instantMine.getState(), mc.world, instantMine.getPos()); + instantMine.addBlockDamage(damageDelta); + + if (instantMine.getBlockDamage() >= speed.get()) + { + boolean canMine = canMine(instantMine.getState()); + boolean canPlace = mc.world.canPlace(instantMine.getState(), instantMine.getPos(), ShapeContext.absent()); + if (canMine) + { + instantMine.markAttemptedMine(); + } + else + { + instantMine.resetMiningTicks(); + if (remine.get() == RemineMode.NORMAL || remine.get() == RemineMode.FAST) + { + instantMine.setTotalBlockDamage(0.0f, 0.0f); + } + + if (manualOverride) + { + manualOverride = false; + abortMining(instantMine); + instantMineAnim.animation.setState(false); + instantMine = null; + } + } + + boolean passedRemine = remine.get() == RemineMode.INSTANT || remineTimer.passed(500); + if (instantMine != null && (remine.get() == RemineMode.INSTANT + && packetInstant.get() && packetMine == null && canPlace || canMine && passedRemine) + && (!checkMultitask() || multitask.get() || swap.get() == Swap.OFF)) + { + stopMining(instantMine); + remineTimer.reset(); + + if (Modules.get().isActive(GenyoAutoCrystal.class) + && Modules.get().get(GenyoAutoCrystal.class).shouldPreForcePlace()) + { + Modules.get().get(GenyoAutoCrystal.class).placeCrystalForTarget(playerTarget, instantMine.getPos().down()); + } + + if (remine.get() == RemineMode.FAST) + { + startMining(instantMine); + } + } + } + } + + // Clear overrides + if (manualOverride && (instantMine == null || instantMine.getGoal() != MiningGoal.MANUAL)) + { + manualOverride = false; + } + + if (antiCrawlOverride && (instantMine == null || instantMine.getGoal() != MiningGoal.PREVENT_CRAWL)) + { + antiCrawlOverride = false; + } + + if (auto.get()) + { + if (!autoMineQueue.isEmpty() && autoMineTickDelay <= 0) + { + MineData nextMine = autoMineQueue.poll(); + if (nextMine != null) + { + startMining(nextMine); + autoMineTickDelay = 5; + } + } + + BlockPos antiCrawlPos = getAntiCrawlPos(playerTarget); + if (antiCrawlOverride) + { + if (mc.player.getPose().equals(EntityPose.SWIMMING)) + { + antiCrawlTicks = 10; + } + + if (antiCrawlTicks <= 0 || !isInstantMineComplete() && antiCrawlPos != null + && !instantMine.getPos().equals(antiCrawlPos)) + { + antiCrawlOverride = false; + } + } + + if (autoMineQueue.isEmpty() && !manualOverride && !antiCrawlOverride) + { + if (antiCrawl.get() && mc.player.getPose().equals(EntityPose.SWIMMING) && antiCrawlPos != null) + { + MineData data = new MineData(antiCrawlPos, strictDirection.get() ? + Managers.INTERACT.getInteractDirection(antiCrawlPos, false) : Direction.UP, MiningGoal.PREVENT_CRAWL); + if (isInstantMineComplete() || !instantMine.equals(data)) + { + startAutoMine(data); + antiCrawlOverride = true; + } + } + + else if (playerTarget != null && !targetChanged) + { + BlockPos targetPos = GEntityUtils.getRoundedBlockPos(playerTarget); + boolean bedrockPhased = GPositionUtils.isBedrock(playerTarget.getBoundingBox(), targetPos) && !playerTarget.isCrawling(); + + if (!isInstantMineComplete() && checkDataY(instantMine, targetPos, bedrockPhased)) + { + abortMining(instantMine); + instantMineAnim.animation.setState(false); + instantMine = null; + } + + else if (packetMine != null && checkDataY(packetMine, targetPos, bedrockPhased)) + { + packetMineAnim.animation.setState(false); + if (packetSwapBack) + { + Managers.INVENTORY.syncToClient(); + packetSwapBack = false; + } + packetMine = null; + waitForPacketMine = false; + } + + else + { + List phasedBlocks = getPhaseBlocks(playerTarget, targetPos, bedrockPhased); + + MineData bestMine; + if (!phasedBlocks.isEmpty()) + { + BlockPos pos1 = phasedBlocks.removeFirst(); + bestMine = new MineData(pos1, strictDirection.get() ? + Managers.INTERACT.getInteractDirection(pos1, false) : Direction.UP); + + if (packetMine == null && doubleBreak.get() || isInstantMineComplete()) + { + startAutoMine(bestMine); + } + } + + else + { + List miningBlocks = getMiningBlocks(playerTarget, targetPos, bedrockPhased); + bestMine = getInstantMine(miningBlocks, bedrockPhased, null); + + if (bestMine != null && (packetMine == null && !changedInstantMine + && doubleBreak.get() || isInstantMineComplete())) + { + startAutoMine(bestMine); + + if (doubleBreak.get() && packetMine == null && !isInstantMineComplete()) + { + MineData secondMine = getInstantMine(miningBlocks, bedrockPhased, bestMine.getPos()); + if (secondMine != null) + { + startAutoMine(secondMine); + } + } + } + } + } + } + + else + { + if (!isInstantMineComplete() && instantMine.getGoal() == MiningGoal.MINING_ENEMY) + { + abortMining(instantMine); + instantMineAnim.animation.setState(false); + instantMine = null; + } + + if (packetMine != null && packetMine.getGoal() == MiningGoal.MINING_ENEMY) + { + packetMineAnim.animation.setState(false); + if (packetSwapBack) + { + Managers.INVENTORY.syncToClient(); + packetSwapBack = false; + } + packetMine = null; + waitForPacketMine = false; + } + } + } + } + } + + @EventHandler + public void onAttackBlock(AttackBlockEvent event) + { + if (mc.player.isCreative() || mc.player.isSpectator()) + { + return; + } + + event.cancel(); + + if (event.state.getBlock().getHardness() == -1.0f || !canMine(event.state) || isMining(event.pos)) + { + return; + } + + MineData data = new MineData(event.pos, event.direction, MiningGoal.MANUAL); + + if (instantMine != null && instantMine.getGoal() == MiningGoal.MINING_ENEMY + || packetMine != null && packetMine.getGoal() == MiningGoal.MINING_ENEMY) + { + manualOverride = true; + } + + if (!doubleBreak.get()) + { + instantMine = data; + startMining(instantMine); + mc.player.swingHand(Hand.MAIN_HAND, false); + return; + } + + boolean updateChanged = false; + if (!isInstantMineComplete() && !changedInstantMine) + { + if (packetMine == null) + { + packetMine = instantMine.copy(); + packetMineAnim = new MineAnimation(packetMine, + new Animation(true, fadeTime.get())); + } + else + { + updateChanged = true; + } + } + + instantMine = data; + startMining(instantMine); + mc.player.swingHand(Hand.MAIN_HAND, false); + if (updateChanged) + { + changedInstantMine = true; + } + } + + @EventHandler + public void onPacketSend(PacketEvent.Send event) + { + if (event.packet instanceof UpdateSelectedSlotC2SPacket && switchReset.get() && instantMine != null) + { + instantMine.setTotalBlockDamage(0.0f, 0.0f); + } + } + + @EventHandler + public void onPacketReceive(PacketEvent.Receive event) + { + if (event.packet instanceof BlockUpdateS2CPacket packet && canMine(packet.getState())) + { + if (antiCrawlOverride && packet.getPos().equals(getAntiCrawlPos(playerTarget))) + { + antiCrawlTicks = 10; + } + } + } + + public void startAutoMine(MineData data) + { + if (!canMine(data.getState()) || isMining(data.getPos())) + { + return; + } + + if (!doubleBreak.get()) + { + instantMine = data; + autoMineQueue.offer(data); + return; + } + + if (changedInstantMine && !isInstantMineComplete() || waitForPacketMine) + { + return; + } + + boolean updateChanged = false; + if (!isInstantMineComplete() && !changedInstantMine) + { + if (packetMine == null) + { + packetMine = instantMine.copy(); + packetMineAnim = new MineAnimation(packetMine, + new Animation(true, fadeTime.get())); + } + else + { + updateChanged = true; + } + } + + instantMine = data; + autoMineQueue.offer(data); + + if (updateChanged) + { + changedInstantMine = true; + } + } + + public MineData getInstantMine(List miningBlocks, boolean bedrockPhased, BlockPos exclude) + { + PriorityQueue validInstantMines = new PriorityQueue<>(); + for (BlockPos blockPos : miningBlocks) + { + if (exclude != null && blockPos.equals(exclude)) continue; + + BlockState state1 = mc.world.getBlockState(blockPos); + if (!isAutoMineBlock(state1.getBlock())) + { + continue; + } + + double dist = mc.player.getEyePos().squaredDistanceTo(blockPos.toCenterPos()); + if (dist > MathUtil.squared(range.get())) + { + continue; + } + + BlockState state2 = mc.world.getBlockState(blockPos.down()); + if (bedrockPhased || state2.isOf(Blocks.OBSIDIAN) || state2.isOf(Blocks.BEDROCK)) + { + Direction direction = strictDirection.get() ? + Managers.INTERACT.getInteractDirection(blockPos, false) : Direction.UP; + + validInstantMines.add(new MineData(blockPos, direction)); + } + } + + if (validInstantMines.isEmpty()) + { + return null; + } + + return validInstantMines.poll(); + } + + public List getPhaseBlocks(PlayerEntity player, BlockPos playerPos, boolean targetBedrockPhased) + { + List phaseBlocks = GPositionUtils.getAllInBox(player.getBoundingBox(), + targetBedrockPhased && head.get() ? playerPos.up() : playerPos); + + phaseBlocks.removeIf(p -> + { + BlockState state = mc.world.getBlockState(p); + if (!isAutoMineBlock(state.getBlock()) || !canMine(state) || isMining(p)) + { + return true; + } + + double dist = mc.player.getEyePos().squaredDistanceTo(p.toCenterPos()); + if (dist > MathUtil.squared(range.get())) + { + return true; + } + + return avoidSelf.get() && intersectsPlayer(p); + }); + + if (targetBedrockPhased && aboveHead.get()) + { + phaseBlocks.add(playerPos.up(2)); + } + + return phaseBlocks; + } + + public List getMiningBlocks(PlayerEntity player, BlockPos playerPos, boolean bedrockPhased) + { + List surroundingBlocks = Modules.get().get(GenyoSurroundV2.class).getSurroundNoDown(player, range.get()); + List miningBlocks; + if (bedrockPhased) + { + List facePlaceBlocks = new ArrayList<>(); + if (head.get()) + { + facePlaceBlocks.addAll(surroundingBlocks.stream().map(BlockPos::up).toList()); + } + + BlockState belowFeet = mc.world.getBlockState(playerPos.down()); + if (canMine(belowFeet)) + { + facePlaceBlocks.add(playerPos.down()); + } + miningBlocks = facePlaceBlocks; + } + else + { + miningBlocks = surroundingBlocks; + } + + miningBlocks.removeIf(p -> avoidSelf.get() && intersectsPlayer(p)); + return miningBlocks; + } + + private BlockPos getAntiCrawlPos(PlayerEntity playerTarget) + { + if (!mc.player.isOnGround()) + { + return null; + } + BlockPos crawlingPos = GEntityUtils.getRoundedBlockPos(mc.player); + boolean playerBelow = playerTarget != null && GEntityUtils.getRoundedBlockPos(playerTarget).getY() < crawlingPos.getY(); + if (playerBelow) + { + BlockState state = mc.world.getBlockState(crawlingPos.down()); + if (isAutoMineBlock(state.getBlock()) && canMine(state)) + { + return crawlingPos.down(); + } + } + else + { + BlockState state = mc.world.getBlockState(crawlingPos.up()); + if (isAutoMineBlock(state.getBlock()) && canMine(state)) + { + return crawlingPos.up(); + } + } + return null; + } + + private boolean checkDataY(MineData data, BlockPos targetPos, boolean bedrockPhased) + { + return data.getGoal() == MiningGoal.MINING_ENEMY && !bedrockPhased && data.getPos().getY() != targetPos.getY(); + } + + private boolean intersectsPlayer(BlockPos pos) + { + List playerBlocks = Modules.get().get(GenyoSurroundV2.class).getPlayerBlocks(mc.player); + List surroundingBlocks = Modules.get().get(GenyoSurroundV2.class).getSurroundNoDown(mc.player); + return playerBlocks.contains(pos) || surroundingBlocks.contains(pos); + } + + @EventHandler + public void onRender3D(Render3DEvent event) + { + if (mc.player.isCreative() || mc.player.isSpectator()) + { + return; + } + + if (!render.get()) return; + + if (instantMineAnim != null && instantMineAnim.animation().getFactor() > 0.01f) + { + renderMiningData(event.renderer, event.tickDelta, + instantMineAnim, true); + } + + if (doubleBreak.get() && packetMineAnim != null && packetMineAnim.animation().getFactor() > 0.01f) + { + renderMiningData(event.renderer, event.tickDelta, + packetMineAnim, false); + } + } + + public void renderMiningData(Renderer3D renderer, float tickDelta, + MineAnimation mineAnimation, boolean instantMine) + { + MineData data = mineAnimation.data(); + Animation animation = mineAnimation.animation(); + int boxAlpha = (int) (40 * animation.getFactor()); + int lineAlpha = (int) (100 * animation.getFactor()); + + Color boxColor; + Color lineColor; + if (smoothColor.get()) + { + boxColor = !canMine(data.getState()) ? colorDone.get().a(boxAlpha) : + ColorUtil.interpolateColor(Math.min(data.getBlockDamage(), 1.0f), colorDone.get().a(boxAlpha), mineColor.get().a(boxAlpha)); + lineColor = !canMine(data.getState()) ? colorDone.get().a(lineAlpha) : + ColorUtil.interpolateColor(Math.min(data.getBlockDamage(), 1.0f), colorDone.get().a(lineAlpha), mineColor.get().a(lineAlpha)); + } + else + { + boxColor = data.getBlockDamage() >= 0.95f || !canMine(data.getState()) ? colorDone.get().a(boxAlpha) : mineColor.get().a(boxAlpha); + lineColor = data.getBlockDamage() >= 0.95f || !canMine(data.getState()) ? colorDone.get().a(lineAlpha) : mineColor.get().a(lineAlpha); + } + + BlockPos mining = data.getPos(); + VoxelShape outlineShape = VoxelShapes.fullCube(); + if (!instantMine || data.getBlockDamage() < speed.get()) + { + outlineShape = data.getState().getOutlineShape(mc.world, mining); + outlineShape = outlineShape.isEmpty() ? VoxelShapes.fullCube() : outlineShape; + } + Box render1 = outlineShape.getBoundingBox(); + Vec3d center = render1.offset(mining).getCenter(); + float total = instantMine ? speed.get() : 1.0f; + float scale = (instantMine && data.getBlockDamage() >= speed.get()) || !canMine(data.getState()) ? 1.0f : + MathHelper.clamp((data.getBlockDamage() + (data.getBlockDamage() - data.getLastDamage()) * tickDelta) / total, 0.0f, 1.0f); + double dx = (render1.maxX - render1.minX) / 2.0; + double dy = (render1.maxY - render1.minY) / 2.0; + double dz = (render1.maxZ - render1.minZ) / 2.0; + final Box scaled = new Box(center, center).expand(dx * scale, dy * scale, dz * scale); + + renderer.box(scaled, boxColor, lineColor, ShapeMode.Both, 0); + } + + public void startMining(MineData data) + { + if (rotate.get()) + { + float[] rotations = RotationUtil.getRotationsTo(mc.player.getEyePos(), data.getPos().toCenterPos()); + if (grim.get()) + { + setRotationSilent(rotations[0], rotations[1]); + } + else + { + setRotation(rotations[0], rotations[1]); + } + } + + if (doubleBreak.get()) + { + if (grimNew.get()) + { + if (!anticheat.get()) + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } + else + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } + + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + Managers.NETWORK.sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + Managers.NETWORK.sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + } + else + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + } + } + else + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } + + if (rotate.get() && grim.get()) + { + Managers.ROTATION.setRotationSilentSync(); + } + + instantMineAnim = new MineAnimation(data, new Animation(true, fadeTime.get())); + } + + public void abortMining(MineData data) + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } + + public void stopMining(MineData data) + { + if (rotate.get()) + { + float[] rotations = RotationUtil.getRotationsTo(mc.player.getEyePos(), data.getPos().toCenterPos()); + if (grim.get()) + { + setRotationSilent(rotations[0], rotations[1]); + } + else + { + setRotation(rotations[0], rotations[1]); + } + } + + int slot = data.getBestSlot(); + if (slot != -1) + { + swapTo(slot); + } + + stopMiningInternal(data); + + if (slot != -1) + { + swapSync(slot); + } + + if (rotate.get() && grim.get()) + { + Managers.ROTATION.setRotationSilentSync(); + } + } + + private void stopMiningInternal(MineData data) + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } + + public boolean isInstantMineComplete() + { + return instantMine == null || instantMine.getBlockDamage() >= speed.get() && !canMine(instantMine.getState()); + } + + public BlockPos getMiningBlock() + { + if (instantMine != null) + { + double damage = instantMine.getBlockDamage() / speed.get(); + if (damage > 0.75) + { + return instantMine.getPos(); + } + } + return null; + } + + private void swapTo(int slot) + { + switch (swap.get()) + { + case NORMAL -> Managers.INVENTORY.setClientSlot(slot); + case SILENT -> Managers.INVENTORY.setSlot(slot); + case SILENT_ALT -> Managers.INVENTORY.setSlotAlt(slot); + } + } + + private void swapSync(int slot) + { + switch (swap.get()) + { + case SILENT -> Managers.INVENTORY.syncToClient(); + case SILENT_ALT -> Managers.INVENTORY.setSlotAlt(slot); + } + } + + public boolean isSilentSwapping() + { + return packetSwapBack; + } + + private boolean isMining(BlockPos blockPos) + { + return instantMine != null && instantMine.getPos().equals(blockPos) || + packetMine != null && packetMine.getPos().equals(blockPos); + } + + private boolean isAutoMineBlock(Block block) + { + if (BlastResistantBlocks.isUnbreakable(block)) + { + return false; + } + return switch (selection.get()) + { + case WHITELIST -> whitelist.get().contains(block); + case BLACKLIST -> !blacklist.get().contains(block); + case ALL -> true; + }; + } + + public boolean canMine(BlockState state) + { + return !state.isAir() && state.getFluidState().isEmpty(); + } + + public static class MineData implements Comparable + { + private static final MinecraftClient mc = MinecraftClient.getInstance(); + private final BlockPos pos; + private final Direction direction; + private final MiningGoal goal; + private int ticksMining; + private float blockDamage, lastDamage; + + public MineData(BlockPos pos, Direction direction) + { + this.pos = pos; + this.direction = direction; + this.goal = MiningGoal.MINING_ENEMY; + } + + public MineData(BlockPos pos, Direction direction, MiningGoal goal) + { + this.pos = pos; + this.direction = direction; + this.goal = goal; + } + + private double getPriority() + { + double dist = mc.player.getEyePos().squaredDistanceTo(pos.down().toCenterPos()); + if (dist <= Modules.get().get(GenyoAutoCrystal.class).getPlaceRange()) + { + return 10.0f; + } + + return 0.0f; + } + + @Override + public int compareTo(@NotNull MineData o) + { + return Double.compare(getPriority(), o.getPriority()); + } + + @Override + public boolean equals(Object obj) + { + return obj instanceof MineData d && d.getPos().equals(pos); + } + + public void resetMiningTicks() + { + ticksMining = 0; + } + + public void markAttemptedMine() + { + ticksMining++; + } + + public void addBlockDamage(float blockDamage) + { + this.lastDamage = this.blockDamage; + this.blockDamage += blockDamage; + } + + public void setTotalBlockDamage(float blockDamage, float lastDamage) + { + this.blockDamage = blockDamage; + this.lastDamage = lastDamage; + } + + public BlockPos getPos() + { + return pos; + } + + public Direction getDirection() + { + return direction; + } + + public MiningGoal getGoal() + { + return goal; + } + + public int getTicksMining() + { + return ticksMining; + } + + public float getBlockDamage() + { + return blockDamage; + } + + public float getLastDamage() + { + return lastDamage; + } + + public static MineData empty() + { + return new MineData(BlockPos.ORIGIN, Direction.UP); + } + + public MineData copy() + { + final MineData data = new MineData(pos, direction, goal); + data.setTotalBlockDamage(blockDamage, lastDamage); + return data; + } + + public BlockState getState() + { + return mc.world.getBlockState(pos); + } + + public int getBestSlot() + { + return Modules.get().get(GenyoAutoTool.class).getBestToolNoFallback(getState()); + } + } + + public record MineAnimation(MineData data, Animation animation) {} + + public enum MiningGoal + { + MANUAL, + MINING_ENEMY, + PREVENT_CRAWL + } + + public enum RemineMode + { + INSTANT, + NORMAL, + FAST + } + + public enum Selection + { + WHITELIST, + BLACKLIST, + ALL + } + + public enum Swap + { + NORMAL, + SILENT, + SILENT_ALT, + OFF + } +} diff --git a/src/main/java/com/genyo/systems/modules/world/GenyoAutoTool.java b/src/main/java/com/genyo/systems/modules/world/GenyoAutoTool.java index 8b34097..92ca9de 100644 --- a/src/main/java/com/genyo/systems/modules/world/GenyoAutoTool.java +++ b/src/main/java/com/genyo/systems/modules/world/GenyoAutoTool.java @@ -38,7 +38,7 @@ public int getBestTool(final BlockState state) { return slot; } - return mc.player.getInventory().selectedSlot; + return mc.player.getInventory().getSelectedSlot(); } public int getBestToolNoFallback(final BlockState state) diff --git a/src/main/java/com/genyo/systems/modules/world/GenyoSelfTrap.java b/src/main/java/com/genyo/systems/modules/world/GenyoSelfTrap.java index 5e1e615..f3c6bf5 100644 --- a/src/main/java/com/genyo/systems/modules/world/GenyoSelfTrap.java +++ b/src/main/java/com/genyo/systems/modules/world/GenyoSelfTrap.java @@ -31,10 +31,7 @@ import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; -import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; -import net.minecraft.network.packet.s2c.play.BundleS2CPacket; -import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; -import net.minecraft.network.packet.s2c.play.ExplosionS2CPacket; +import net.minecraft.network.packet.s2c.play.*; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; @@ -43,6 +40,7 @@ import java.util.*; + public class GenyoSelfTrap extends PlacerModule { public GenyoSelfTrap() { @@ -125,7 +123,22 @@ public GenyoSelfTrap() { .defaultValue(false) .build() ); + private final Setting mineProtect = sgGeneral.add(new BoolSetting.Builder() + .name("Mine Protect") + .description("Places a block on surround when an enemy mines past a set threshold") + .defaultValue(false) + .build() + ); + private final Setting mineProtectThreshold = sgGeneral.add(new FloatSetting.Builder() + .name("Mine Threshold") + .description("Mining progress % at which to place a protective block (0-100)") + .defaultValue(50.0f) + .min(0.0f) + .max(100.0f) + .visible(() -> mineProtect.get()) + .build() + ); private final Setting support = sgGeneral.add(new BoolSetting.Builder() .name("Support") .description("Creates a floor for the trap if there is none") @@ -187,6 +200,8 @@ public GenyoSelfTrap() { private List placements = new ArrayList<>(); private final Map packets = new HashMap<>(); private final Map fadeList = new HashMap<>(); + private final Map mineProgress = new HashMap<>(); + private final Map mineProtectCooldown = new HashMap<>(); private double prevY; @Override @@ -202,6 +217,8 @@ public void onDeactivate() { placements.clear(); packets.clear(); fadeList.clear(); + mineProgress.clear(); + mineProtectCooldown.clear(); } @EventHandler @@ -280,6 +297,39 @@ public void onPacketReceive(PacketEvent.Receive event) { private void handlePackets(Packet serverPacket) { + if (serverPacket instanceof BlockBreakingProgressS2CPacket packet && mineProtect.get()) { + BlockPos minedPos = packet.getPos(); + int entityId = packet.getEntityId(); + int stage = packet.getProgress(); + + if (stage < 0) { + mineProgress.remove(entityId); + return; + } + + if (!trap.contains(minedPos)) return; + + float progressPercent = (stage / 9.0f) * 100.0f; + long[] prev = mineProgress.get(entityId); + float prevPercent = (prev != null) ? (prev[1] / 9.0f) * 100.0f : 0.0f; + + mineProgress.put(entityId, new long[]{minedPos.asLong(), stage}); + + if (prevPercent < mineProtectThreshold.get() && progressPercent >= mineProtectThreshold.get()) { + Long lastReact = mineProtectCooldown.get(minedPos); + if (lastReact != null && System.currentTimeMillis() - lastReact < 500) return; + + final int slot = getResistantBlockItem(); + if (slot == -1) return; + + for (BlockPos adjacent : getAdjacentPlacements(minedPos)) { + placeBlock(adjacent, slot); + } + mineProtectCooldown.put(minedPos, System.currentTimeMillis()); + } + return; + } + if (timing.get() != Timing.SEQUENTIAL) return; if (serverPacket instanceof BlockUpdateS2CPacket packet) @@ -291,10 +341,7 @@ private void handlePackets(Packet serverPacket) if (blockState.isReplaceable() && Objects.requireNonNull(mc.world).canPlace(DEFAULT_OBSIDIAN_STATE, targetPos, ShapeContext.absent())) { final int slot = getResistantBlockItem(); - if (slot == -1) - { - return; - } + if (slot == -1) return; placeBlock(targetPos, slot); } else if (BlastResistantBlocks.isBlastResistant(blockState)) @@ -304,10 +351,7 @@ else if (BlastResistantBlocks.isBlastResistant(blockState)) } } - if (blocksPlaced > shiftTicks.get() * 2) // Give some leniency if we are getting place on - { - return; - } + if (blocksPlaced > shiftTicks.get() * 2) return; if (serverPacket instanceof ExplosionS2CPacket packet && prePlaceExplosion.get()) { @@ -315,10 +359,7 @@ else if (BlastResistantBlocks.isBlastResistant(blockState)) if (trap.contains(pos)) { final int slot = getResistantBlockItem(); - if (slot == -1) - { - return; - } + if (slot == -1) return; placeBlock(pos, slot); } } @@ -328,22 +369,31 @@ else if (BlastResistantBlocks.isBlastResistant(blockState)) { for (BlockPos pos : trap) { - if (!pos.equals(BlockPos.ofFloored(packet.getX(), packet.getY(), packet.getZ()))) - { - continue; - } + if (!pos.equals(BlockPos.ofFloored(packet.getX(), packet.getY(), packet.getZ()))) continue; final int slot = getResistantBlockItem(); - if (slot == -1) - { - return; - } + if (slot == -1) return; placeBlock(pos, slot); break; } } } + private List getAdjacentPlacements(BlockPos minedPos) + { + List result = new ArrayList<>(); + for (Direction dir : Direction.values()) + { + BlockPos adjacent = minedPos.offset(dir); + + if (adjacent.equals(mc.player.getBlockPos()) || adjacent.equals(mc.player.getBlockPos().up())) continue; + if (!mc.world.getBlockState(adjacent).isReplaceable()) continue; + if (!mc.world.canPlace(DEFAULT_OBSIDIAN_STATE, adjacent, ShapeContext.absent())) continue; + + result.add(adjacent); + } + return result; + } private void placeBlock(BlockPos pos, int slot) { if (!buggy.get()) { @@ -356,6 +406,7 @@ private void placeBlock(BlockPos pos, int slot) } else { if (InvUtils.findInHotbar(Items.OBSIDIAN).slot() == -1) return; + Managers.INVENTORY.setSlot(slot); BlockUtils.place(pos, InvUtils.findInHotbar(Items.OBSIDIAN), rotate.get(), 0, true); } packets.put(pos, System.currentTimeMillis()); diff --git a/src/main/java/com/genyo/systems/modules/world/GenyoSurroundV2.java b/src/main/java/com/genyo/systems/modules/world/GenyoSurroundV2.java index a1df57f..40d9e91 100644 --- a/src/main/java/com/genyo/systems/modules/world/GenyoSurroundV2.java +++ b/src/main/java/com/genyo/systems/modules/world/GenyoSurroundV2.java @@ -30,10 +30,7 @@ import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; -import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; -import net.minecraft.network.packet.s2c.play.BundleS2CPacket; -import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; -import net.minecraft.network.packet.s2c.play.ExplosionS2CPacket; +import net.minecraft.network.packet.s2c.play.*; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; @@ -124,6 +121,22 @@ public GenyoSurroundV2() { .defaultValue(false) .build() ); + private final Setting mineProtect = sgGeneral.add(new BoolSetting.Builder() + .name("Mine Protect") + .description("Places a block on surround when an enemy mines past a set threshold") + .defaultValue(false) + .build() + ); + + private final Setting mineProtectThreshold = sgGeneral.add(new FloatSetting.Builder() + .name("Mine Threshold") + .description("Mining progress % at which to place a protective block (0-100)") + .defaultValue(50.0f) + .min(0.0f) + .max(100.0f) + .visible(() -> mineProtect.get()) + .build() + ); private final Setting support = sgGeneral.add(new BoolSetting.Builder() .name("Support") @@ -186,6 +199,8 @@ public GenyoSurroundV2() { private List placements = new ArrayList<>(); private final Map packets = new HashMap<>(); private final Map fadeList = new HashMap<>(); + private final Map mineProgress = new HashMap<>(); + private final Map mineProtectCooldown = new HashMap<>(); private double prevY; @Override @@ -201,6 +216,8 @@ public void onDeactivate() { placements.clear(); packets.clear(); fadeList.clear(); + mineProgress.clear(); + mineProtectCooldown.clear(); } @EventHandler @@ -277,6 +294,39 @@ public void onPacketReceive(PacketEvent.Receive event) { private void handlePackets(Packet serverPacket) { + if (serverPacket instanceof BlockBreakingProgressS2CPacket packet && mineProtect.get()) { + BlockPos minedPos = packet.getPos(); + int entityId = packet.getEntityId(); + int stage = packet.getProgress(); + + if (stage < 0) { + mineProgress.remove(entityId); + return; + } + + if (!surround.contains(minedPos)) return; + + float progressPercent = (stage / 9.0f) * 100.0f; + long[] prev = mineProgress.get(entityId); + float prevPercent = (prev != null) ? (prev[1] / 9.0f) * 100.0f : 0.0f; + + mineProgress.put(entityId, new long[]{minedPos.asLong(), stage}); + + if (prevPercent < mineProtectThreshold.get() && progressPercent >= mineProtectThreshold.get()) { + Long lastReact = mineProtectCooldown.get(minedPos); + if (lastReact != null && System.currentTimeMillis() - lastReact < 500) return; + + final int slot = getResistantBlockItem(); + if (slot == -1) return; + + for (BlockPos adjacent : getAdjacentPlacements(minedPos)) { + placeBlock(adjacent, slot); + } + mineProtectCooldown.put(minedPos, System.currentTimeMillis()); + } + return; + } + if (timing.get() != Timing.SEQUENTIAL) return; if (serverPacket instanceof BlockUpdateS2CPacket packet) @@ -288,10 +338,7 @@ private void handlePackets(Packet serverPacket) if (blockState.isReplaceable() && Objects.requireNonNull(mc.world).canPlace(DEFAULT_OBSIDIAN_STATE, targetPos, ShapeContext.absent())) { final int slot = getResistantBlockItem(); - if (slot == -1) - { - return; - } + if (slot == -1) return; placeBlock(targetPos, slot); } else if (BlastResistantBlocks.isBlastResistant(blockState)) @@ -301,10 +348,7 @@ else if (BlastResistantBlocks.isBlastResistant(blockState)) } } - if (blocksPlaced > shiftTicks.get() * 2) // Give some leniency if we are getting place on - { - return; - } + if (blocksPlaced > shiftTicks.get() * 2) return; if (serverPacket instanceof ExplosionS2CPacket packet && prePlaceExplosion.get()) { @@ -312,10 +356,7 @@ else if (BlastResistantBlocks.isBlastResistant(blockState)) if (surround.contains(pos)) { final int slot = getResistantBlockItem(); - if (slot == -1) - { - return; - } + if (slot == -1) return; placeBlock(pos, slot); } } @@ -325,22 +366,32 @@ else if (BlastResistantBlocks.isBlastResistant(blockState)) { for (BlockPos pos : surround) { - if (!pos.equals(BlockPos.ofFloored(packet.getX(), packet.getY(), packet.getZ()))) - { - continue; - } + if (!pos.equals(BlockPos.ofFloored(packet.getX(), packet.getY(), packet.getZ()))) continue; final int slot = getResistantBlockItem(); - if (slot == -1) - { - return; - } + if (slot == -1) return; placeBlock(pos, slot); break; } } } + private List getAdjacentPlacements(BlockPos minedPos) + { + List result = new ArrayList<>(); + for (Direction dir : Direction.values()) + { + BlockPos adjacent = minedPos.offset(dir); + + if (adjacent.equals(mc.player.getBlockPos()) || adjacent.equals(mc.player.getBlockPos().up())) continue; + if (!mc.world.getBlockState(adjacent).isReplaceable()) continue; + if (!mc.world.canPlace(DEFAULT_OBSIDIAN_STATE, adjacent, ShapeContext.absent())) continue; + + result.add(adjacent); + } + return result; + } + private void placeBlock(BlockPos pos, int slot) { if (!buggy.get()) { diff --git a/src/main/java/com/genyo/systems/settings/FloatSetting.java b/src/main/java/com/genyo/systems/settings/FloatSetting.java index c0152ef..b0a207d 100644 --- a/src/main/java/com/genyo/systems/settings/FloatSetting.java +++ b/src/main/java/com/genyo/systems/settings/FloatSetting.java @@ -49,7 +49,7 @@ protected NbtCompound save(NbtCompound tag) { @Override public Float load(NbtCompound tag) { - set(tag.getFloat("value")); + set(tag.getFloat("value").orElse(0f)); return get(); } diff --git a/src/main/java/com/genyo/systems/settings/playerlist/ListPlayer.java b/src/main/java/com/genyo/systems/settings/playerlist/ListPlayer.java index 26ed6e0..70b1d43 100644 --- a/src/main/java/com/genyo/systems/settings/playerlist/ListPlayer.java +++ b/src/main/java/com/genyo/systems/settings/playerlist/ListPlayer.java @@ -9,8 +9,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; import java.util.Objects; import java.util.UUID; @@ -19,7 +18,7 @@ public class ListPlayer implements ISerializable, Comparable load(NbtCompound tag) { NbtList groupNames = (NbtList) tag.get("group_names"); NbtList messages = (NbtList) tag.get("messages"); for (int i = 0; i < indexes.size(); i++) { - String msg = messages.get(i).asString(); - String groupName = groupNames.get(i).asString(); + String msg = messages.get(i).asString().orElse(""); + String groupName = groupNames.get(i).asString().orElse(""); List players = new ArrayList<>(); NbtList playersList = (NbtList) tag.get("players"); @@ -160,7 +160,7 @@ protected List load(NbtCompound tag) { for (NbtElement val : playersList) { NbtList currentPlayers = (NbtList) playersList.get(i); currentPlayers.forEach(player -> { - ListPlayer listPlayer = new ListPlayer(player.asString()); + ListPlayer listPlayer = new ListPlayer(player.asString().orElse("")); players.add(listPlayer); }); } diff --git a/src/main/java/com/genyo/utils/GInvUtils.java b/src/main/java/com/genyo/utils/GInvUtils.java index 3be585a..456aa92 100644 --- a/src/main/java/com/genyo/utils/GInvUtils.java +++ b/src/main/java/com/genyo/utils/GInvUtils.java @@ -62,7 +62,7 @@ public static SearchInvResult findInHotBar(Searcher searcher) { public static void switchTo(int slot) { if (mc.player == null || mc.getNetworkHandler() == null) return; - if (mc.player.getInventory().selectedSlot == slot && Managers.INVENTORY.getServerSlot() == slot) + if (mc.player.getInventory().getSelectedSlot() == slot && Managers.INVENTORY.getServerSlot() == slot) return; mc.player.getInventory().setSelectedSlot(slot); Managers.INVENTORY.syncToClient(); @@ -77,16 +77,16 @@ public static SearchInvResult getAntiWeaknessItem() { if (mc.player == null) return SearchInvResult.notFound(); Item mainHand = mc.player.getMainHandStack().getItem(); - if ((mainHand instanceof SwordItem) - || (mainHand instanceof PickaxeItem) + if (mc.player.getMainHandStack().isIn(ItemTags.SWORDS) + || mc.player.getMainHandStack().isIn(ItemTags.PICKAXES) || (mainHand instanceof AxeItem) || (mainHand instanceof ShovelItem)) { - return new SearchInvResult(mc.player.getInventory().selectedSlot, true, mc.player.getMainHandStack()); + return new SearchInvResult(mc.player.getInventory().getSelectedSlot(), true, mc.player.getMainHandStack()); } return findInHotBar( - itemStack -> itemStack.getItem() instanceof SwordItem - || itemStack.getItem() instanceof PickaxeItem + itemStack -> itemStack.isIn(ItemTags.SWORDS) + || itemStack.isIn(ItemTags.PICKAXES) || itemStack.getItem() instanceof AxeItem || itemStack.getItem() instanceof ShovelItem ); diff --git a/src/main/java/com/genyo/utils/HudUtils.java b/src/main/java/com/genyo/utils/HudUtils.java index ebcbb68..7d8895e 100644 --- a/src/main/java/com/genyo/utils/HudUtils.java +++ b/src/main/java/com/genyo/utils/HudUtils.java @@ -3,7 +3,7 @@ import meteordevelopment.meteorclient.systems.hud.HudRenderer; import meteordevelopment.meteorclient.utils.render.color.Color; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.util.math.MatrixStack; + import net.minecraft.item.ItemStack; import static meteordevelopment.meteorclient.MeteorClient.mc; @@ -11,17 +11,15 @@ public class HudUtils { public static void drawItem(DrawContext drawContext, ItemStack itemStack, int x, int y, float scale) { - MatrixStack matrices = drawContext.getMatrices(); - matrices.push(); - matrices.scale(scale, scale, 1f); - matrices.translate(0, 0, 401); // Thanks Mojang + drawContext.getMatrices().pushMatrix(); + drawContext.getMatrices().scale(scale, scale); int scaledX = (int) (x / scale); int scaledY = (int) (y / scale); drawContext.drawItem(itemStack, scaledX, scaledY); - matrices.pop(); + drawContext.getMatrices().popMatrix(); } } diff --git a/src/main/java/com/genyo/utils/player/InteractionUtil.java b/src/main/java/com/genyo/utils/player/InteractionUtil.java index 33f33de..d364f87 100644 --- a/src/main/java/com/genyo/utils/player/InteractionUtil.java +++ b/src/main/java/com/genyo/utils/player/InteractionUtil.java @@ -18,8 +18,7 @@ import net.minecraft.util.math.*; import net.minecraft.world.RaycastContext; import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; +import org.jetbrains.annotations.Nullable; import java.util.*; @@ -40,7 +39,7 @@ public class InteractionUtil { public static Map awaiting = new HashMap<>(); public static Vec3d getEyesPos(@NotNull Entity entity) { - return entity.getPos().add(0, entity.getEyeHeight(entity.getPose()), 0); + return entity.getEyePos().add(0, entity.getEyeHeight(entity.getPose()), 0); } public static float @NotNull [] calculateAngle(Vec3d to) { @@ -91,7 +90,7 @@ public static BlockHitResult getPlaceResult(@NotNull BlockPos bp, Interact inter } BlockHitResult result = null; if (interact == Interact.Legit) { - Vec3d p = getVisibleDirectionPoint(support.facing, support.position, 0, 6); //TODO Implement Range + Vec3d p = getVisibleDirectionPoint(support.facing, support.position, 0, 6); if (p != null) return new BlockHitResult(p, support.facing, support.position, false); } else { @@ -107,10 +106,8 @@ public static BlockHitResult getPlaceResult(@NotNull BlockPos bp, Interact inter return switch (dir) { case UP -> new Box(.15f, 1f, .15f, .85f, 1f, .85f); case DOWN -> new Box(.15f, 0f, .15f, .85f, 0f, .85f); - case EAST -> new Box(1f, .15f, .15f, 1f, .85f, .85f); case WEST -> new Box(0f, .15f, .15f, 0f, .85f, .85f); - case NORTH -> new Box(.15f, .15f, 0f, .85f, .85f, 0f); case SOUTH -> new Box(.15f, .15f, 1f, .85f, .85f, 1f); }; @@ -119,60 +116,39 @@ public static BlockHitResult getPlaceResult(@NotNull BlockPos bp, Interact inter public static @Nullable Vec3d getVisibleDirectionPoint(@NotNull Direction dir, @NotNull BlockPos bp, float wallRange, float range) { Box brutBox = getDirectionBox(dir); - // EAST, WEST if (brutBox.maxX - brutBox.minX == 0) for (double y = brutBox.minY; y < brutBox.maxY; y += 0.1f) for (double z = brutBox.minZ; z < brutBox.maxZ; z += 0.1f) { Vec3d point = new Vec3d(bp.getX() + brutBox.minX, bp.getY() + y, bp.getZ() + z); - - if (shouldSkipPoint(point, bp, dir, wallRange, range)) - continue; - + if (shouldSkipPoint(point, bp, dir, wallRange, range)) continue; return point; } - - // DOWN, UP if (brutBox.maxY - brutBox.minY == 0) for (double x = brutBox.minX; x < brutBox.maxX; x += 0.1f) for (double z = brutBox.minZ; z < brutBox.maxZ; z += 0.1f) { Vec3d point = new Vec3d(bp.getX() + x, bp.getY() + brutBox.minY, bp.getZ() + z); - - if (shouldSkipPoint(point, bp, dir, wallRange, range)) - continue; - + if (shouldSkipPoint(point, bp, dir, wallRange, range)) continue; return point; } - - // NORTH, SOUTH if (brutBox.maxZ - brutBox.minZ == 0) for (double x = brutBox.minX; x < brutBox.maxX; x += 0.1f) for (double y = brutBox.minY; y < brutBox.maxY; y += 0.1f) { Vec3d point = new Vec3d(bp.getX() + x, bp.getY() + y, bp.getZ() + brutBox.minZ); - - if (shouldSkipPoint(point, bp, dir, wallRange, range)) - continue; - + if (shouldSkipPoint(point, bp, dir, wallRange, range)) continue; return point; } - return null; } private static boolean shouldSkipPoint(Vec3d point, BlockPos bp, Direction dir, float wallRange, float range) { RaycastContext context = new RaycastContext(InteractionUtil.getEyesPos(mc.player), point, RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, mc.player); BlockHitResult result = mc.world.raycast(context); - float dst = InteractionUtil.squaredDistanceFromEyes(point); - - if (result != null - && result.getType() == HitResult.Type.BLOCK - && !result.getBlockPos().equals(bp) - && dst > wallRange * wallRange) + if (result != null && result.getType() == HitResult.Type.BLOCK && !result.getBlockPos().equals(bp) && dst > wallRange * wallRange) return true; - return dst > range * range; } @@ -191,32 +167,20 @@ public static boolean isSolid(BlockPos bp) { double upDelta = getEyesPos(mc.player).y - (positionVector.add(0, 0.5, 0).y); double downDelta = getEyesPos(mc.player).y - (positionVector.add(0, -0.5, 0).y); - if (westDelta > 0 && isSolid(bp.west())) - visibleSides.add(Direction.EAST); - if (westDelta < 0 && isSolid(bp.east())) - visibleSides.add(Direction.WEST); - if (eastDelta < 0 && isSolid(bp.east())) - visibleSides.add(Direction.WEST); - if (eastDelta > 0 && isSolid(bp.west())) - visibleSides.add(Direction.EAST); - - if (northDelta > 0 && isSolid(bp.north())) - visibleSides.add(Direction.SOUTH); - if (northDelta < 0 && isSolid(bp.south())) - visibleSides.add(Direction.NORTH); - if (southDelta < 0 && isSolid(bp.south())) - visibleSides.add(Direction.NORTH); - if (southDelta > 0 && isSolid(bp.north())) - visibleSides.add(Direction.SOUTH); - - if (upDelta > 0 && isSolid(bp.down())) - visibleSides.add(Direction.UP); - if (upDelta < 0 && isSolid(bp.up())) - visibleSides.add(Direction.DOWN); - if (downDelta < 0 && isSolid(bp.up())) - visibleSides.add(Direction.DOWN); - if (downDelta > 0 && isSolid(bp.down())) - visibleSides.add(Direction.UP); + if (westDelta > 0 && isSolid(bp.west())) visibleSides.add(Direction.EAST); + if (westDelta < 0 && isSolid(bp.east())) visibleSides.add(Direction.WEST); + if (eastDelta < 0 && isSolid(bp.east())) visibleSides.add(Direction.WEST); + if (eastDelta > 0 && isSolid(bp.west())) visibleSides.add(Direction.EAST); + + if (northDelta > 0 && isSolid(bp.north())) visibleSides.add(Direction.SOUTH); + if (northDelta < 0 && isSolid(bp.south())) visibleSides.add(Direction.NORTH); + if (southDelta < 0 && isSolid(bp.south())) visibleSides.add(Direction.NORTH); + if (southDelta > 0 && isSolid(bp.north())) visibleSides.add(Direction.SOUTH); + + if (upDelta > 0 && isSolid(bp.down())) visibleSides.add(Direction.UP); + if (upDelta < 0 && isSolid(bp.up())) visibleSides.add(Direction.DOWN); + if (downDelta < 0 && isSolid(bp.up())) visibleSides.add(Direction.DOWN); + if (downDelta > 0 && isSolid(bp.down())) visibleSides.add(Direction.UP); return visibleSides; } @@ -226,19 +190,14 @@ public static boolean isSolid(BlockPos bp) { if (mc.world.getBlockState(bp.add(0, -1, 0)).isSolid() || awaiting.containsKey(bp.add(0, -1, 0))) list.add(new BlockPosWithFacing(bp.add(0, -1, 0), Direction.UP)); - if (mc.world.getBlockState(bp.add(0, 1, 0)).isSolid() || awaiting.containsKey(bp.add(0, 1, 0))) list.add(new BlockPosWithFacing(bp.add(0, 1, 0), Direction.DOWN)); - if (mc.world.getBlockState(bp.add(-1, 0, 0)).isSolid() || awaiting.containsKey(bp.add(-1, 0, 0))) list.add(new BlockPosWithFacing(bp.add(-1, 0, 0), Direction.EAST)); - if (mc.world.getBlockState(bp.add(1, 0, 0)).isSolid() || awaiting.containsKey(bp.add(1, 0, 0))) list.add(new BlockPosWithFacing(bp.add(1, 0, 0), Direction.WEST)); - if (mc.world.getBlockState(bp.add(0, 0, 1)).isSolid() || awaiting.containsKey(bp.add(0, 0, 1))) list.add(new BlockPosWithFacing(bp.add(0, 0, 1), Direction.NORTH)); - if (mc.world.getBlockState(bp.add(0, 0, -1)).isSolid() || awaiting.containsKey(bp.add(0, 0, -1))) list.add(new BlockPosWithFacing(bp.add(0, 0, -1), Direction.SOUTH)); @@ -255,22 +214,20 @@ public static boolean needSneak(Block in) { } public static boolean placeBlock(BlockPos bp, Rotate rotate, Interact interact, PlaceMode mode, int slot, boolean returnSlot, boolean ignoreEntities) { - int prevItem = mc.player.getInventory().selectedSlot; + int prevItem = mc.player.getInventory().getSelectedSlot(); if (slot != -1) GInvUtils.switchTo(slot); else return false; boolean result = placeBlock(bp, rotate, interact, mode, ignoreEntities); - if (returnSlot) GInvUtils.switchTo(prevItem); return result; } public static boolean placeBlock(BlockPos bp, Rotate rotate, Interact interact, PlaceMode mode, @NotNull SearchInvResult invResult, boolean returnSlot, boolean ignoreEntities) { - int prevItem = mc.player.getInventory().selectedSlot; + int prevItem = mc.player.getInventory().getSelectedSlot(); invResult.switchTo(); boolean result = placeBlock(bp, rotate, interact, mode, ignoreEntities); if (returnSlot) GInvUtils.switchTo(prevItem); - return result; } @@ -283,15 +240,12 @@ public static boolean placeBlock(BlockPos bp, Rotate rotate, Interact interact, if (sprint) mc.player.networkHandler.sendPacket(new ClientCommandC2SPacket(mc.player, ClientCommandC2SPacket.Mode.STOP_SPRINTING)); - if (sneak) - mc.player.networkHandler.sendPacket(new ClientCommandC2SPacket(mc.player, ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY)); + if (sneak) mc.player.setSneaking(true); float[] angle = calculateAngle(result.getPos()); switch (rotate) { - case None -> { - - } + case None -> {} case Default -> mc.player.networkHandler.sendPacket(new PlayerMoveC2SPacket.LookAndOnGround(angle[0], angle[1], mc.player.isOnGround(), mc.player.horizontalCollision)); case Grim -> mc.player.networkHandler.sendPacket(new PlayerMoveC2SPacket.Full(mc.player.getX(), mc.player.getY(), mc.player.getZ(), angle[0], angle[1], mc.player.isOnGround(), mc.player.horizontalCollision)); } @@ -307,8 +261,7 @@ public static boolean placeBlock(BlockPos bp, Rotate rotate, Interact interact, if (rotate == Rotate.Grim) mc.player.networkHandler.sendPacket(new PlayerMoveC2SPacket.Full(mc.player.getX(), mc.player.getY(), mc.player.getZ(), mc.player.getYaw(), mc.player.getPitch(), mc.player.isOnGround(), mc.player.horizontalCollision)); - if (sneak) - mc.player.networkHandler.sendPacket(new ClientCommandC2SPacket(mc.player, ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY)); + if (sneak) mc.player.setSneaking(false); // ← was RELEASE_SHIFT_KEY if (sprint) mc.player.networkHandler.sendPacket(new ClientCommandC2SPacket(mc.player, ClientCommandC2SPacket.Mode.START_SPRINTING)); @@ -317,25 +270,9 @@ public static boolean placeBlock(BlockPos bp, Rotate rotate, Interact interact, return true; } - public record BlockPosWithFacing(BlockPos position, Direction facing) { - } - - public enum PlaceMode { - Packet, - Normal - } - - public enum Rotate { - None, - Default, - Grim - } - - public enum Interact { - Vanilla, - Strict, - Legit, - AirPlace - } + public record BlockPosWithFacing(BlockPos position, Direction facing) {} + public enum PlaceMode { Packet, Normal } + public enum Rotate { None, Default, Grim } + public enum Interact { Vanilla, Strict, Legit, AirPlace } } diff --git a/src/main/java/com/genyo/utils/player/MovementUtil.java b/src/main/java/com/genyo/utils/player/MovementUtil.java index c304578..28f54c7 100644 --- a/src/main/java/com/genyo/utils/player/MovementUtil.java +++ b/src/main/java/com/genyo/utils/player/MovementUtil.java @@ -1,36 +1,29 @@ package com.genyo.utils.player; +import com.genyo.mixin.accessor.AccessorInput; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.EquipmentSlot; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec2f; import static meteordevelopment.meteorclient.MeteorClient.mc; public class MovementUtil { - public static void applySneak() - { + public static void applySneak() { final float modifier = MathHelper.clamp(0.3f + (EnchantmentUtil.getLevel(mc.player.getEquippedStack(EquipmentSlot.FEET), Enchantments.SWIFT_SNEAK) * 0.15F), 0.0f, 1.0f); - mc.player.input.movementForward *= modifier; - mc.player.input.movementSideways *= modifier; + Vec2f vec = mc.player.input.getMovementInput(); + ((AccessorInput) mc.player.input).setMovementVector(new Vec2f(vec.x * modifier, vec.y * modifier)); } - /** - * @return - */ - public static boolean isInputtingMovement() - { + public static boolean isInputtingMovement() { return mc.options.forwardKey.isPressed() || mc.options.backKey.isPressed() || mc.options.leftKey.isPressed() || mc.options.rightKey.isPressed(); } - /** - * @return - */ - public static boolean isMoving() - { + public static boolean isMoving() { double d = mc.player.getX() - mc.player.lastRenderX; double e = mc.player.getY() - mc.player.lastRenderY; double f = mc.player.getZ() - mc.player.lastRenderZ; @@ -45,8 +38,8 @@ public static double[] forwardWithoutStrafe(final double d) { } public static double[] forward(final double d) { - float f = mc.player.input.movementForward; - float f2 = mc.player.input.movementSideways; + float f = mc.player.input.getMovementInput().y; + float f2 = mc.player.input.getMovementInput().x; float f3 = mc.player.getYaw(); if (f != 0.0f) { if (f2 > 0.0f) { @@ -68,13 +61,8 @@ public static double[] forward(final double d) { return new double[]{d4, d5}; } - /** - * @return - */ - public static boolean isMovingInput() - { - return mc.player.input.movementForward != 0.0f - || mc.player.input.movementSideways != 0.0f; + public static boolean isMovingInput() { + Vec2f vec = mc.player.input.getMovementInput(); + return vec.y != 0.0f || vec.x != 0.0f; } - } diff --git a/src/main/java/com/genyo/utils/player/SearchInvResult.java b/src/main/java/com/genyo/utils/player/SearchInvResult.java index 434fa4f..5584c33 100644 --- a/src/main/java/com/genyo/utils/player/SearchInvResult.java +++ b/src/main/java/com/genyo/utils/player/SearchInvResult.java @@ -21,7 +21,7 @@ public static SearchInvResult notFound() { public boolean isHolding() { if (mc.player == null) return false; - return mc.player.getInventory().selectedSlot == slot; + return mc.player.getInventory().getSelectedSlot() == slot; } public boolean isInHotBar() { diff --git a/src/main/java/com/genyo/utils/render/SInterpolation.java b/src/main/java/com/genyo/utils/render/SInterpolation.java index 4c9a87b..14dc9b5 100644 --- a/src/main/java/com/genyo/utils/render/SInterpolation.java +++ b/src/main/java/com/genyo/utils/render/SInterpolation.java @@ -8,32 +8,32 @@ public class SInterpolation { /** - * @param prev + * @param last * @param value * @param factor * @return */ - public static double interpolateDouble(double prev, double value, double factor) + public static double interpolateDouble(double last, double value, double factor) { - return prev + ((value - prev) * factor); + return last + ((value - last) * factor); } /** - * @param prevBox + * @param lastBox * @param box * @return */ - public static Box getInterpolatedBox(Box prevBox, Box box) + public static Box getInterpolatedBox(Box lastBox, Box box) { - double delta = mc.isPaused() ? 1f : mc.getRenderTickCounter().getTickDelta(true); + double delta = mc.isPaused() ? 1f : mc.getRenderTickCounter().getTickProgress(true); - return new Box(interpolateDouble(prevBox.minX, box.minX, delta), - interpolateDouble(prevBox.minY, box.minY, delta), - interpolateDouble(prevBox.minZ, box.minZ, delta), - interpolateDouble(prevBox.maxX, box.maxX, delta), - interpolateDouble(prevBox.maxY, box.maxY, delta), - interpolateDouble(prevBox.maxZ, box.maxZ, delta)); + return new Box(interpolateDouble(lastBox.minX, box.minX, delta), + interpolateDouble(lastBox.minY, box.minY, delta), + interpolateDouble(lastBox.minZ, box.minZ, delta), + interpolateDouble(lastBox.maxX, box.maxX, delta), + interpolateDouble(lastBox.maxY, box.maxY, delta), + interpolateDouble(lastBox.maxZ, box.maxZ, delta)); } /** @@ -43,8 +43,8 @@ public static Box getInterpolatedBox(Box prevBox, Box box) public static Box getInterpolatedEntityBox(Entity entity) { Box box = entity.getBoundingBox(); - Box prevBox = entity.getBoundingBox().offset(entity.prevX - entity.getX(), entity.prevY - entity.getY(), entity.prevZ - entity.getZ()); - return getInterpolatedBox(prevBox, box); + Box lastBox = entity.getBoundingBox().offset(entity.lastX - entity.getX(), entity.lastY - entity.getY(), entity.lastZ - entity.getZ()); + return getInterpolatedBox(lastBox, box); } } diff --git a/src/main/java/com/genyo/utils/world/ExplosionUtil.java b/src/main/java/com/genyo/utils/world/ExplosionUtil.java index 41119d3..a950918 100644 --- a/src/main/java/com/genyo/utils/world/ExplosionUtil.java +++ b/src/main/java/com/genyo/utils/world/ExplosionUtil.java @@ -24,6 +24,8 @@ import net.minecraft.world.RaycastContext; import org.apache.commons.lang3.mutable.MutableInt; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import java.util.function.BiFunction; @@ -97,9 +99,9 @@ public static double getDamageTo(final Entity entity, Vec3d vec3d2 = Vec3d.ZERO; if (extrapolationTicks != 0) { - double ox = (x - entity.prevX) * extrapolationTicks; - double oy = (y - entity.prevY) * extrapolationTicks * 0.3; - double oz = (z - entity.prevZ) * extrapolationTicks; + double ox = (x - entity.lastRenderX) * extrapolationTicks; + double oy = (y - entity.lastRenderY) * extrapolationTicks * 0.3; + double oz = (z - entity.lastRenderZ) * extrapolationTicks; x += ox; y += oy; z += oz; @@ -150,9 +152,9 @@ public static double getDamageTo(final Entity entity, Vec3d vec3d2 = Vec3d.ZERO; if (extrapolationTicks != 0) { - double ox = (x - entity.prevX) * extrapolationTicks; - double oy = (y - entity.prevY) * extrapolationTicks * 0.3; - double oz = (z - entity.prevZ) * extrapolationTicks; + double ox = (x - entity.lastRenderX) * extrapolationTicks; + double oy = (y - entity.lastRenderY) * extrapolationTicks * 0.3; + double oz = (z - entity.lastRenderZ) * extrapolationTicks; x += ox; y += oy; z += oz; @@ -193,9 +195,9 @@ public static double getDamageTo(final Entity entity, Vec3d vec3d2 = Vec3d.ZERO; if (extrapolationTicks != 0) { - double ox = (x - entity.prevX) * extrapolationTicks; - double oy = (y - entity.prevY) * extrapolationTicks * 0.3; - double oz = (z - entity.prevZ) * extrapolationTicks; + double ox = (x - entity.lastRenderX) * extrapolationTicks; + double oy = (y - entity.lastRenderY) * extrapolationTicks * 0.3; + double oz = (z - entity.lastRenderZ) * extrapolationTicks; x += ox; y += oy; z += oz; @@ -231,9 +233,9 @@ public static double getDamageTo(final Entity entity, Vec3d vec3d2 = Vec3d.ZERO; if (extrapolationTicks != 0) { - double ox = (x - entity.prevX) * extrapolationTicks; - double oy = (y - entity.prevY) * extrapolationTicks * 0.3; - double oz = (z - entity.prevZ) * extrapolationTicks; + double ox = (x - entity.lastRenderX) * extrapolationTicks; + double oy = (y - entity.lastRenderY) * extrapolationTicks * 0.3; + double oz = (z - entity.lastRenderZ) * extrapolationTicks; x += ox; y += oy; z += oz; @@ -312,7 +314,12 @@ private static float getArmor(LivingEntity entity) private static float getProtectionReduction(Entity player, double damage, DamageSource source, boolean assumeBestArmor) { if (player instanceof LivingEntity livingEntity) { - float protLevel = getProtectionAmount(livingEntity.getArmorItems(), assumeBestArmor); + List armorItems = new ArrayList<>(); + armorItems.add(livingEntity.getEquippedStack(EquipmentSlot.HEAD)); + armorItems.add(livingEntity.getEquippedStack(EquipmentSlot.CHEST)); + armorItems.add(livingEntity.getEquippedStack(EquipmentSlot.LEGS)); + armorItems.add(livingEntity.getEquippedStack(EquipmentSlot.FEET)); + float protLevel = getProtectionAmount(armorItems, assumeBestArmor); return DamageUtil.getInflictedDamage((float) damage, protLevel); } return 0.0f; diff --git a/src/main/resources/assets/genyo/sounds.json b/src/main/resources/assets/genyo/sounds.json index de913d0..1ff2a2c 100644 --- a/src/main/resources/assets/genyo/sounds.json +++ b/src/main/resources/assets/genyo/sounds.json @@ -33,5 +33,20 @@ "sounds": [ "genyo:kiwi" ] + }, + "gui_hover": { + "sounds": [ + "genyo:gui_hover" + ] + }, + "gui_click_left": { + "sounds": [ + "genyo:gui_click_left" + ] + }, + "gui_click_right": { + "sounds": [ + "genyo:gui_click_right" + ] } } diff --git a/src/main/resources/assets/genyo/sounds/gui_click_left.ogg b/src/main/resources/assets/genyo/sounds/gui_click_left.ogg new file mode 100644 index 0000000000000000000000000000000000000000..6a2fa613fa943b0dfe464491aec4e67dbdf469be GIT binary patch literal 7133 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 aH+^y~jNKTqGhg8KLji$mOE$sZ=)V9nq^hz2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/genyo/sounds/gui_click_right.ogg b/src/main/resources/assets/genyo/sounds/gui_click_right.ogg new file mode 100644 index 0000000000000000000000000000000000000000..10b4e682459167e7681a19760ea2c918243dcb4a GIT binary patch literal 5409 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/genyo/sounds/gui_hover.ogg b/src/main/resources/assets/genyo/sounds/gui_hover.ogg new file mode 100644 index 0000000000000000000000000000000000000000..db19ed0e4fcf9c8e95e2171a67a5eac02c03372b GIT binary patch literal 5432 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 W+D>hmYT{l@7rSz&c1B}=Hux{8u`I0s literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/genyo/textures/cape_dev.png b/src/main/resources/assets/genyo/textures/cape_dev.png new file mode 100644 index 0000000000000000000000000000000000000000..2168b421429ed438abf11f94664a7ef8660562b1 GIT binary patch literal 45801 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 Date: Sat, 30 May 2026 15:00:40 +0200 Subject: [PATCH 4/4] Updated README for new ver --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c98745c..3055d53 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@