├── .editorconfig ├── .github └── workflows │ └── build.yml ├── .gitignore ├── README.md ├── build.gradle.kts ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── main ├── java └── me │ └── redcarlos │ └── netherfreedom │ ├── NFAddon.java │ ├── modules │ ├── hud │ │ └── WelcomeHudNF.java │ └── main │ │ ├── AutoWalkNF.java │ │ ├── BaritoneMiner.java │ │ ├── DiggingTools.java │ │ ├── HotbarManager.java │ │ ├── NetherBorer.java │ │ ├── OffhandManager.java │ │ └── RotationNF.java │ └── utils │ └── NFUtils.java └── resources ├── assets └── icon.png ├── fabric.mod.json └── netherfreedom.accesswidener /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | indent_style = space 4 | insert_final_newline = true 5 | trim_trailing_whitespace = true 6 | indent_size = 4 7 | 8 | [*.{json, yml}] 9 | indent_size = 2 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout repository 9 | uses: actions/checkout@v4 10 | 11 | - name: Set up Java 12 | uses: actions/setup-java@v4 13 | with: 14 | distribution: 'adopt' 15 | java-version: 21 16 | 17 | - name: Build 18 | run: ./gradlew build 19 | 20 | - name: Upload artifacts 21 | uses: actions/upload-artifact@v4 22 | with: 23 | name: build-artifacts 24 | path: build/libs/ 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gradle 2 | 3 | .gradle/ 4 | build/ 5 | out/ 6 | classes/ 7 | 8 | # eclipse 9 | 10 | *.launch 11 | 12 | # idea 13 | 14 | .idea/ 15 | *.iml 16 | *.ipr 17 | *.iws 18 | 19 | # vscode 20 | 21 | .settings/ 22 | .vscode/ 23 | bin/ 24 | .classpath 25 | .project 26 | 27 | # macos 28 | 29 | *.DS_Store 30 | 31 | # fabric 32 | 33 | run/ 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | logo 3 |

Nether Freedom Addon

4 |

Nether Freedom Addon is specifically to dig the nether freedom project on endcrystal.me

5 | 6 | Verified Addon 7 | Version 8 | Minecraft Version 9 |
10 | 11 | ## How to use 12 | - Download the lastest Meteor Client build. 13 | - Move NF Addon in your `.minecraft/mods` folder where you have installed Meteor. 14 | 15 | ## Features 16 | - AutoWalkNF 17 | - BaritoneMiner 18 | - DiggingTools 19 | - HotbarManager 20 | - NetherBorer 21 | - OffhandManager 22 | - RotationNF 23 | - Welcome HUD 24 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("fabric-loom") version "1.10-SNAPSHOT" 3 | } 4 | 5 | base { 6 | archivesName = project.property("archives_base_name").toString() 7 | version = project.property("mod_version").toString() 8 | group = project.property("maven_group").toString() 9 | } 10 | 11 | repositories { 12 | maven("https://maven.meteordev.org/releases") { 13 | name = "meteor-maven" 14 | } 15 | 16 | maven("https://maven.meteordev.org/snapshots") { 17 | name = "meteor-maven-snapshots" 18 | } 19 | 20 | maven("https://babbaj.github.io/maven/") { 21 | name = "babbaj-maven" 22 | } 23 | } 24 | 25 | dependencies { 26 | // Fabric 27 | minecraft("com.mojang:minecraft:${project.property("minecraft_version")}") 28 | mappings("net.fabricmc:yarn:${project.property("yarn_mappings")}:v2") 29 | modImplementation("net.fabricmc:fabric-loader:${project.property("loader_version")}") 30 | 31 | // Meteor 32 | modImplementation("meteordevelopment:meteor-client:${project.property("minecraft_version")}-SNAPSHOT") 33 | 34 | // Baritone 35 | modImplementation("dev.babbaj:nether-pathfinder:1.4.1") 36 | modImplementation("meteordevelopment:baritone:${project.property("minecraft_version")}-SNAPSHOT") 37 | } 38 | 39 | tasks { 40 | processResources { 41 | val propertiesMap = mapOf( 42 | "version" to project.version, 43 | "minecraft_version" to project.property("minecraft_version"), 44 | "loader_version" to project.property("loader_version") 45 | ) 46 | 47 | inputs.properties(propertiesMap) 48 | filesMatching("fabric.mod.json") { 49 | expand(propertiesMap) 50 | } 51 | } 52 | 53 | withType { 54 | options.encoding = "UTF-8" 55 | options.release = 21 56 | } 57 | 58 | java { 59 | sourceCompatibility = JavaVersion.VERSION_21 60 | targetCompatibility = JavaVersion.VERSION_21 61 | } 62 | } 63 | 64 | loom { 65 | accessWidenerPath = file("src/main/resources/netherfreedom.accesswidener") 66 | } 67 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx2G 2 | 3 | # Fabric Properties (https://fabricmc.net/develop/) 4 | minecraft_version=1.21.4 5 | yarn_mappings=1.21.4+build.8 6 | loader_version=0.16.10 7 | 8 | # Mod Properties 9 | mod_version=1.5 10 | maven_group=netherfreedom.package 11 | archives_base_name=NF-Addon 12 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PoopenfartenDevelopment/NetherFreedom-Addon/0f6063c178d68e59f05257c5a00588f87de47ab2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s' "$PWD" ) || exit 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | if ! command -v java >/dev/null 2>&1 137 | then 138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 139 | 140 | Please set the JAVA_HOME variable in your environment to match the 141 | location of your Java installation." 142 | fi 143 | fi 144 | 145 | # Increase the maximum file descriptors if we can. 146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 147 | case $MAX_FD in #( 148 | max*) 149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 150 | # shellcheck disable=SC2039,SC3045 151 | MAX_FD=$( ulimit -H -n ) || 152 | warn "Could not query maximum file descriptor limit" 153 | esac 154 | case $MAX_FD in #( 155 | '' | soft) :;; #( 156 | *) 157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 158 | # shellcheck disable=SC2039,SC3045 159 | ulimit -n "$MAX_FD" || 160 | warn "Could not set maximum file descriptor limit to $MAX_FD" 161 | esac 162 | fi 163 | 164 | # Collect all arguments for the java command, stacking in reverse order: 165 | # * args from the command line 166 | # * the main class name 167 | # * -classpath 168 | # * -D...appname settings 169 | # * --module-path (only if needed) 170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 171 | 172 | # For Cygwin or MSYS, switch paths to Windows format before running java 173 | if "$cygwin" || "$msys" ; then 174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 176 | 177 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 178 | 179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 180 | for arg do 181 | if 182 | case $arg in #( 183 | -*) false ;; # don't mess with options #( 184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 185 | [ -e "$t" ] ;; #( 186 | *) false ;; 187 | esac 188 | then 189 | arg=$( cygpath --path --ignore --mixed "$arg" ) 190 | fi 191 | # Roll the args list around exactly as many times as the number of 192 | # args, so each arg winds up back in the position where it started, but 193 | # possibly modified. 194 | # 195 | # NB: a `for` loop captures its iteration list before it begins, so 196 | # changing the positional parameters here affects neither the number of 197 | # iterations, nor the values presented in `arg`. 198 | shift # remove old arg 199 | set -- "$@" "$arg" # push replacement arg 200 | done 201 | fi 202 | 203 | 204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 206 | 207 | # Collect all arguments for the java command: 208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 209 | # and any embedded shellness will be escaped. 210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 211 | # treated as '${Hostname}' itself on the command line. 212 | 213 | set -- \ 214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 215 | -classpath "$CLASSPATH" \ 216 | org.gradle.wrapper.GradleWrapperMain \ 217 | "$@" 218 | 219 | # Stop when "xargs" is not available. 220 | if ! command -v xargs >/dev/null 2>&1 221 | then 222 | die "xargs is not available" 223 | fi 224 | 225 | # Use "xargs" to parse quoted args. 226 | # 227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 228 | # 229 | # In Bash we could simply go: 230 | # 231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 232 | # set -- "${ARGS[@]}" "$@" 233 | # 234 | # but POSIX shell has neither arrays nor command substitution, so instead we 235 | # post-process each arg (as a line of input to sed) to backslash-escape any 236 | # character that might be a shell metacharacter, then use eval to reverse 237 | # that process (while maintaining the separation between arguments), and wrap 238 | # the whole thing up as a single "set" statement. 239 | # 240 | # This will of course break if any of these variables contains a newline or 241 | # an unmatched quote. 242 | # 243 | 244 | eval "set -- $( 245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 246 | xargs -n1 | 247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 248 | tr '\n' ' ' 249 | )" '"$@"' 250 | 251 | exec "$JAVACMD" "$@" 252 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { 4 | name = 'Fabric' 5 | url = 'https://maven.fabricmc.net/' 6 | } 7 | mavenCentral() 8 | gradlePluginPortal() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/NFAddon.java: -------------------------------------------------------------------------------- 1 | package me.redcarlos.netherfreedom; 2 | 3 | import com.mojang.logging.LogUtils; 4 | import me.redcarlos.netherfreedom.modules.hud.WelcomeHudNF; 5 | import me.redcarlos.netherfreedom.modules.main.*; 6 | import meteordevelopment.meteorclient.addons.MeteorAddon; 7 | import meteordevelopment.meteorclient.pathing.BaritoneUtils; 8 | import meteordevelopment.meteorclient.systems.Systems; 9 | import meteordevelopment.meteorclient.systems.hud.Hud; 10 | import meteordevelopment.meteorclient.systems.hud.HudGroup; 11 | import meteordevelopment.meteorclient.systems.modules.Category; 12 | import meteordevelopment.meteorclient.systems.modules.Modules; 13 | import net.fabricmc.loader.api.FabricLoader; 14 | import net.fabricmc.loader.api.metadata.ModMetadata; 15 | import net.minecraft.item.Items; 16 | import org.slf4j.Logger; 17 | 18 | public class NFAddon extends MeteorAddon { 19 | public static final Logger LOG = LogUtils.getLogger(); 20 | public static final ModMetadata METADATA = FabricLoader.getInstance().getModContainer("nfaddon").orElseThrow().getMetadata(); 21 | public static final String VERSION = METADATA.getVersion().toString(); 22 | public static final Category Main = new Category("NF Addon", Items.NETHERITE_PICKAXE.getDefaultStack()); 23 | public static final HudGroup Hud = new HudGroup("NF Addon"); 24 | 25 | @Override 26 | public void onInitialize() { 27 | LOG.info("Initializing NF Addon " + NFAddon.VERSION); 28 | 29 | // Modules 30 | Modules modules = Modules.get(); 31 | 32 | // Main 33 | modules.add(new AutoWalkNF()); 34 | modules.add(new DiggingTools()); 35 | modules.add(new HotbarManager()); 36 | modules.add(new NetherBorer()); 37 | modules.add(new RotationNF()); 38 | modules.add(new OffhandManager()); 39 | 40 | // HUD 41 | Hud hud = Systems.get(Hud.class); 42 | hud.register(WelcomeHudNF.INFO); 43 | 44 | if (BaritoneUtils.IS_AVAILABLE) { 45 | modules.add(new BaritoneMiner()); 46 | } 47 | } 48 | 49 | @Override 50 | public String getPackage() { 51 | return "me.redcarlos.netherfreedom"; 52 | } 53 | 54 | @Override 55 | public void onRegisterCategories() { 56 | Modules.registerCategory(Main); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/modules/hud/WelcomeHudNF.java: -------------------------------------------------------------------------------- 1 | package me.redcarlos.netherfreedom.modules.hud; 2 | 3 | import me.redcarlos.netherfreedom.NFAddon; 4 | import meteordevelopment.meteorclient.settings.EnumSetting; 5 | import meteordevelopment.meteorclient.settings.Setting; 6 | import meteordevelopment.meteorclient.settings.SettingGroup; 7 | import meteordevelopment.meteorclient.systems.hud.HudElement; 8 | import meteordevelopment.meteorclient.systems.hud.HudElementInfo; 9 | import meteordevelopment.meteorclient.systems.hud.HudRenderer; 10 | import meteordevelopment.meteorclient.systems.hud.elements.TextHud; 11 | import meteordevelopment.meteorclient.systems.modules.Modules; 12 | import meteordevelopment.meteorclient.systems.modules.misc.NameProtect; 13 | 14 | import java.util.Calendar; 15 | 16 | import static meteordevelopment.meteorclient.MeteorClient.mc; 17 | 18 | public class WelcomeHudNF extends HudElement { 19 | public static final HudElementInfo INFO = new HudElementInfo<>(NFAddon.Hud, "welcome-hud-NF", "Displays a friendly welcome.", WelcomeHudNF::new); 20 | 21 | private String leftText; 22 | private String rightText; 23 | private double leftWidth; 24 | 25 | public WelcomeHudNF() { 26 | super(INFO); 27 | } 28 | 29 | @Override 30 | public void tick(HudRenderer renderer) { 31 | leftText = "Welcome to NetherFreedom, "; 32 | rightText = Modules.get().get(NameProtect.class).getName(mc.getSession().getUsername()); 33 | 34 | leftWidth = renderer.textWidth(leftText); 35 | double rightWidth = renderer.textWidth(rightText); 36 | 37 | box.setSize((leftWidth + rightWidth), renderer.textHeight()); 38 | } 39 | 40 | @Override 41 | public void render(HudRenderer renderer) { 42 | double x = this.x; 43 | double y = this.y; 44 | 45 | if (isInEditor()) { 46 | renderer.text("WelcomeHUD-NF", x, y, TextHud.getSectionColor(0), true); 47 | return; 48 | } 49 | 50 | renderer.text(leftText, x, y, TextHud.getSectionColor(0), true); 51 | renderer.text(rightText, x + leftWidth, y, TextHud.getSectionColor(1), true); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/modules/main/AutoWalkNF.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). 3 | * Copyright (c) Meteor Development. 4 | * Enhanced by RedCarlos26 5 | */ 6 | 7 | package me.redcarlos.netherfreedom.modules.main; 8 | 9 | import me.redcarlos.netherfreedom.NFAddon; 10 | import meteordevelopment.meteorclient.events.world.TickEvent; 11 | import meteordevelopment.meteorclient.settings.BoolSetting; 12 | import meteordevelopment.meteorclient.settings.IntSetting; 13 | import meteordevelopment.meteorclient.settings.Setting; 14 | import meteordevelopment.meteorclient.settings.SettingGroup; 15 | import meteordevelopment.meteorclient.systems.modules.Module; 16 | import meteordevelopment.meteorclient.utils.misc.input.Input; 17 | import meteordevelopment.meteorclient.utils.player.FindItemResult; 18 | import meteordevelopment.meteorclient.utils.player.InvUtils; 19 | import meteordevelopment.meteorclient.utils.world.TickRate; 20 | import meteordevelopment.orbit.EventHandler; 21 | import net.minecraft.client.option.KeyBinding; 22 | import net.minecraft.item.Items; 23 | 24 | public class AutoWalkNF extends Module { 25 | private final SettingGroup sgGeneral = settings.getDefaultGroup(); 26 | 27 | private final Setting pauseOnLag = sgGeneral.add(new BoolSetting.Builder() 28 | .name("pause-on-lag") 29 | .description("Pauses walking while the server stops responding.") 30 | .defaultValue(true) 31 | .build() 32 | ); 33 | 34 | private final Setting resumeTPS = sgGeneral.add(new IntSetting.Builder() 35 | .name("resume-tps") 36 | .description("Server tick speed at which to resume walking.") 37 | .defaultValue(16) 38 | .range(1, 19) 39 | .sliderRange(1, 19) 40 | .visible(pauseOnLag::get) 41 | .build() 42 | ); 43 | 44 | private final Setting keepY = sgGeneral.add(new BoolSetting.Builder() 45 | .name("y-value-toggle") 46 | .description("Toggles itself when you fall below your original height.") 47 | .defaultValue(true) 48 | .build() 49 | ); 50 | 51 | private final Setting pickToggle = sgGeneral.add(new BoolSetting.Builder() 52 | .name("pickaxe-toggle") 53 | .description("Toggles itself when you run out of pickaxes.") 54 | .defaultValue(true) 55 | .build() 56 | ); 57 | 58 | private final Setting gapToggle = sgGeneral.add(new BoolSetting.Builder() 59 | .name("gap-toggle") 60 | .description("Toggles itself when you run out of enchanted golden apples.") 61 | .defaultValue(true) 62 | .build() 63 | ); 64 | 65 | private double originY; 66 | private boolean sentLagMessage; 67 | 68 | public AutoWalkNF() { 69 | super(NFAddon.Main, "auto-walk-NF", "Automatically walks forward. Optimized for NetherFreedom."); 70 | } 71 | 72 | @Override 73 | public void onActivate() { 74 | if (mc.player == null) return; 75 | 76 | originY = Math.abs(mc.player.getY()); 77 | sentLagMessage = false; 78 | } 79 | 80 | @Override 81 | public void onDeactivate() { 82 | unpress(); 83 | } 84 | 85 | @EventHandler 86 | private void onTick(TickEvent.Pre event) { 87 | if (pauseOnLag.get()) { 88 | if (TickRate.INSTANCE.getTimeSinceLastTick() > 1.4f) { 89 | if (!sentLagMessage) { 90 | error("Server isn't responding, pausing."); 91 | } 92 | sentLagMessage = true; 93 | unpress(); 94 | return; 95 | } 96 | 97 | if (sentLagMessage) { 98 | if (TickRate.INSTANCE.getTickRate() > resumeTPS.get()) { 99 | sentLagMessage = false; 100 | } else return; 101 | } 102 | } 103 | 104 | setPressed(mc.options.forwardKey, true); 105 | 106 | if (keepY.get()) { 107 | if (mc.player == null) return; 108 | // -0.125 is so players can still walk on soul sand and similar blocks while digging 109 | if (mc.player.getY() < originY - 0.125) { 110 | info("Fell below original height, disabling."); 111 | toggle(); 112 | return; 113 | } 114 | } 115 | 116 | if (pickToggle.get()) { 117 | FindItemResult pickaxe = InvUtils.find(itemStack -> itemStack.getItem() == Items.DIAMOND_PICKAXE || itemStack.getItem() == Items.NETHERITE_PICKAXE); 118 | if (!pickaxe.found()) { 119 | error("No pickaxe found, disabling."); 120 | toggle(); 121 | return; 122 | } 123 | } 124 | 125 | if (gapToggle.get()) { 126 | FindItemResult gapple = InvUtils.find(itemStack -> itemStack.getItem() == Items.ENCHANTED_GOLDEN_APPLE); 127 | if (!gapple.found()) { 128 | error("No gap found, disabling."); 129 | toggle(); 130 | } 131 | } 132 | } 133 | 134 | private void unpress() { 135 | setPressed(mc.options.forwardKey, false); 136 | } 137 | 138 | private void setPressed(KeyBinding key, boolean pressed) { 139 | key.setPressed(pressed); 140 | Input.setKeyState(key, pressed); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/modules/main/BaritoneMiner.java: -------------------------------------------------------------------------------- 1 | package me.redcarlos.netherfreedom.modules.main; 2 | 3 | import baritone.api.BaritoneAPI; 4 | import baritone.api.IBaritone; 5 | import baritone.api.Settings; 6 | import baritone.api.pathing.goals.GoalBlock; 7 | import me.redcarlos.netherfreedom.NFAddon; 8 | import me.redcarlos.netherfreedom.utils.NFUtils; 9 | import meteordevelopment.meteorclient.events.game.GameLeftEvent; 10 | import meteordevelopment.meteorclient.events.game.OpenScreenEvent; 11 | import meteordevelopment.meteorclient.events.render.Render3DEvent; 12 | import meteordevelopment.meteorclient.events.world.TickEvent; 13 | import meteordevelopment.meteorclient.gui.GuiTheme; 14 | import meteordevelopment.meteorclient.gui.widgets.WWidget; 15 | import meteordevelopment.meteorclient.gui.widgets.containers.WHorizontalList; 16 | import meteordevelopment.meteorclient.gui.widgets.containers.WVerticalList; 17 | import meteordevelopment.meteorclient.gui.widgets.pressable.WButton; 18 | import meteordevelopment.meteorclient.renderer.ShapeMode; 19 | import meteordevelopment.meteorclient.settings.*; 20 | import meteordevelopment.meteorclient.systems.modules.Module; 21 | import meteordevelopment.meteorclient.systems.modules.Modules; 22 | import meteordevelopment.meteorclient.utils.misc.Keybind; 23 | import meteordevelopment.meteorclient.utils.misc.MeteorStarscript; 24 | import meteordevelopment.meteorclient.utils.player.FindItemResult; 25 | import meteordevelopment.meteorclient.utils.player.InvUtils; 26 | import meteordevelopment.meteorclient.utils.player.PlayerUtils; 27 | import meteordevelopment.meteorclient.utils.render.color.Color; 28 | import meteordevelopment.meteorclient.utils.world.BlockUtils; 29 | import meteordevelopment.orbit.EventHandler; 30 | import meteordevelopment.starscript.compiler.Compiler; 31 | import meteordevelopment.starscript.compiler.Parser; 32 | import net.minecraft.block.Blocks; 33 | import net.minecraft.client.gui.screen.DisconnectedScreen; 34 | import net.minecraft.client.gui.screen.ingame.ShulkerBoxScreen; 35 | import net.minecraft.item.Item; 36 | import net.minecraft.item.Items; 37 | import net.minecraft.screen.slot.SlotActionType; 38 | import net.minecraft.util.Hand; 39 | import net.minecraft.util.hit.BlockHitResult; 40 | import net.minecraft.util.math.BlockPos; 41 | import net.minecraft.util.math.Direction; 42 | import net.minecraft.util.math.Vec3d; 43 | 44 | public class BaritoneMiner extends Module { 45 | 46 | /* 47 | todo:future features list 48 | 1. option for it to stop at certain goal position 49 | 2. option to disconnect on running out of pickaxes 50 | */ 51 | 52 | private final SettingGroup sgGeneral = settings.getDefaultGroup(); 53 | private final SettingGroup sgShape = settings.createGroup("Shape"); 54 | 55 | private final IBaritone baritone = BaritoneAPI.getProvider().getPrimaryBaritone(); 56 | private final Settings baritoneSettings = BaritoneAPI.getSettings(); 57 | 58 | private final Setting cornerOne = sgShape.add(new BlockPosSetting.Builder() 59 | .name("corner-1") 60 | .description("Position of 1st corner.") 61 | .defaultValue(new BlockPos(10, 120, 10)) 62 | .build() 63 | ); 64 | 65 | private final Setting cornerTwo = sgShape.add(new BlockPosSetting.Builder() 66 | .name("corner-2") 67 | .description("Position of 2nd corner.") 68 | .defaultValue(new BlockPos(-10, 120, -10)) 69 | .build() 70 | ); 71 | 72 | private final Setting nukerOffset = sgGeneral.add(new IntSetting.Builder() 73 | .name("nuker-offset") 74 | .description("Distance for the bot to offset after reaching the end of a line.") 75 | .defaultValue(8) 76 | .range(0, 15) 77 | .sliderRange(1, 15) 78 | .build() 79 | ); 80 | 81 | private final Setting pathStart = sgGeneral.add(new BoolSetting.Builder() 82 | .name("path-to-start") 83 | .description("Force baritone to path to a corner before starting.") 84 | .defaultValue(true) 85 | .build() 86 | ); 87 | 88 | private final Setting renderCorners = sgGeneral.add(new BoolSetting.Builder() 89 | .name("render-corners") 90 | .description("Renders the 2 corners.") 91 | .defaultValue(true) 92 | .build() 93 | ); 94 | 95 | private final Setting disableOnDisconnect = sgGeneral.add(new BoolSetting.Builder() 96 | .name("disable-on-disconnect") 97 | .description("Disables when you disconnect.") 98 | .defaultValue(true) 99 | .build() 100 | ); 101 | 102 | private final Setting refillPicks = sgGeneral.add(new BoolSetting.Builder() 103 | .name("refill-pickaxes-from-shulker") 104 | .description("Refills pickaxes from shulkers when you run out.") 105 | .defaultValue(true) 106 | .build() 107 | ); 108 | 109 | private final Setting pauseBind = sgGeneral.add(new KeybindSetting.Builder() 110 | .name("pause") 111 | .description("Pauses baritone.") 112 | .defaultValue(Keybind.none()) 113 | .build() 114 | ); 115 | 116 | public BaritoneMiner() { 117 | super(NFAddon.Main, "(BETA)-baritone-miner", "Paths to dig automatically."); 118 | } 119 | 120 | private Direction toEndOfLineDir, toAdvanceDir, shulkerPlaceDir = null; 121 | private BlockPos endOfLinePos, barPos, offsetPos, currPlayerPos, shulkerPlacePos, savedPos = null; 122 | private boolean offsetting, bindPressed, isPaused, refilling, placedShulker, defined = false; 123 | private int initialNetherrackMined, initialPicksBroken, finalNetherrackMined, finalPicksBroken; 124 | private int length = 0; 125 | 126 | Modules modules = Modules.get(); 127 | 128 | @Override 129 | public void onActivate() { 130 | baritoneSettings.blockPlacementPenalty.value = 0.0; 131 | baritoneSettings.assumeWalkOnLava.value = true; 132 | baritoneSettings.allowPlace.value = true; 133 | baritoneSettings.mineScanDroppedItems.value = true; 134 | 135 | if (!defined && !pathStart.get()) { 136 | start(); 137 | } else if (!defined && pathStart.get()) { 138 | setGoal(cornerOne.get()); 139 | } else { 140 | setGoal(barPos); 141 | } 142 | 143 | isPaused = false; 144 | 145 | initialNetherrackMined = getNetherrackMined(); 146 | initialPicksBroken = getPicksBroken(); 147 | } 148 | 149 | @Override 150 | public void onDeactivate() { 151 | baritone.getPathingBehavior().cancelEverything(); 152 | 153 | finalNetherrackMined = getNetherrackMined(); 154 | finalPicksBroken = getPicksBroken(); 155 | 156 | int netherrackMinedResult = getNetherrackResult(); 157 | int picksBrokenResult = getPickaxesResult(); 158 | 159 | info("Blocks mined: %d", netherrackMinedResult); 160 | info("Pickaxes broken: %d", picksBrokenResult); 161 | } 162 | 163 | @EventHandler 164 | public void onTick(TickEvent.Pre event) throws InterruptedException { 165 | if (mc.player == null || mc.world == null) return; 166 | 167 | currPlayerPos = mc.player.getBlockPos(); 168 | 169 | if (pathStart.get() && currPlayerPos.equals(cornerOne.get())) { 170 | start(); 171 | } 172 | 173 | if (getPickAmount() == 0 && !placedShulker && refillPicks.get()) { 174 | if (baritone.getPathingBehavior().isPathing()) baritone.getCommandManager().execute("pause"); 175 | refilling = true; 176 | // Saves current goal, so it can later resume after refilling on pickaxes 177 | GoalBlock baritoneGoal = (GoalBlock) baritone.getCustomGoalProcess().getGoal(); 178 | savedPos = new BlockPos(baritoneGoal.x, baritoneGoal.y, baritoneGoal.z); 179 | 180 | // Places shulker and toggles borer rotating and placing another shulker if the spot is invalid 181 | shulkerPlacePos = currPlayerPos.offset(shulkerPlaceDir, 2); 182 | 183 | if (modules.get(NetherBorer.class).isActive()) modules.get(NetherBorer.class).toggle(); 184 | 185 | if (!BlockUtils.place(shulkerPlacePos, findShulkerBox(), true, 0, true, true, false)) { 186 | info("Trying to place shulker at " + shulkerPlacePos.getX() + " " + shulkerPlacePos.getZ()); 187 | shulkerPlaceDir = shulkerPlaceDir.rotateYClockwise(); 188 | placedShulker = false; 189 | shulkerPlacePos = null; 190 | return; 191 | } 192 | 193 | placedShulker = true; 194 | return; 195 | } 196 | 197 | if (getPickAmount() == 0 && placedShulker) { 198 | openShulker(shulkerPlacePos); 199 | // If no pickaxes were moved then it will reset and place another shulker 90 degrees clockwise to the player 200 | if (mc.currentScreen instanceof ShulkerBoxScreen) { 201 | if (grabAllPickaxes() == 0) { 202 | mc.currentScreen.close(); 203 | shulkerPlaceDir = shulkerPlaceDir.rotateYClockwise(); 204 | placedShulker = false; 205 | shulkerPlacePos = null; 206 | return; 207 | } 208 | mc.currentScreen.close(); 209 | } 210 | setGoal(shulkerPlacePos); 211 | if (!baritone.getPathingBehavior().isPathing()) baritone.getCommandManager().execute("resume"); 212 | } 213 | 214 | // Breaks, paths, then pauses where the shulker was placed then resets to continue mining 215 | if (currPlayerPos.equals(shulkerPlacePos)) { 216 | // Very monkey fix for right now 217 | if (!baritone.getPathingBehavior().isPathing()) baritone.getCommandManager().execute("pause"); 218 | Thread.sleep(1000); 219 | if (!baritone.getPathingBehavior().isPathing()) baritone.getCommandManager().execute("resume"); 220 | 221 | setGoal(savedPos); 222 | shulkerPlacePos = null; 223 | savedPos = null; 224 | placedShulker = false; 225 | refilling = false; 226 | 227 | if (!modules.get(NetherBorer.class).isActive()) modules.get(NetherBorer.class).toggle(); 228 | } 229 | 230 | // The mode it will be working in most of the time 231 | if (!currPlayerPos.equals(barPos) && !offsetting && !refilling) { 232 | try { 233 | BlockPos underPos = barPos.offset(Direction.DOWN); 234 | if (underPos.getY() == 120 && mc.world.getBlockState(underPos).getBlock() != Blocks.LAVA && mc.world.getBlockState(underPos).isAir()) { 235 | barPos = underPos.offset(toEndOfLineDir); 236 | } else if (mc.world.getBlockState(barPos).getBlock() == Blocks.LAVA) { 237 | barPos = barPos.offset(Direction.UP); 238 | } 239 | 240 | // If the player is one block before the goal then it will set the goal one further to keep it from stuttering 241 | BlockPos preBarPos = new BlockPos(barPos.offset(toEndOfLineDir.getOpposite())); 242 | if (currPlayerPos.equals(preBarPos)) { 243 | barPos = new BlockPos(barPos.offset(toEndOfLineDir)); 244 | } 245 | setGoal(barPos); 246 | 247 | /** 248 | // Places a block under the goal to keep baritone from pulling any funny business 249 | if (underPos.getY() != cornerOne.get().getY()) { 250 | placeUnder(barPos); 251 | } 252 | */ 253 | } catch (Exception ignored) {} 254 | } 255 | 256 | if (currPlayerPos.equals(barPos)) { 257 | barPos = barPos.offset(toEndOfLineDir); 258 | } 259 | 260 | if (currPlayerPos.equals(endOfLinePos)) { 261 | offsetPos = new BlockPos(endOfLinePos.offset(toAdvanceDir, nukerOffset.get())); 262 | setGoal(offsetPos); 263 | offsetting = true; 264 | } 265 | 266 | if (currPlayerPos.equals(offsetPos)) { 267 | toEndOfLineDir = toEndOfLineDir.getOpposite(); 268 | shulkerPlaceDir = toEndOfLineDir.getOpposite(); 269 | endOfLinePos = new BlockPos(offsetPos.offset(toEndOfLineDir, length)); 270 | barPos = new BlockPos(offsetPos.offset(toEndOfLineDir, 2)); 271 | offsetting = false; 272 | offsetPos = null; 273 | } 274 | } 275 | 276 | @EventHandler 277 | private void onTick(TickEvent.Post event) { 278 | if (!pauseBind.get().isPressed()) bindPressed = false; 279 | 280 | if (pauseBind.get().isPressed() && !bindPressed && !isPaused) { 281 | baritone.getCommandManager().execute("pause"); 282 | isPaused = true; 283 | bindPressed = true; 284 | return; 285 | } 286 | 287 | if (pauseBind.get().isPressed() && !bindPressed && isPaused) { 288 | baritone.getCommandManager().execute("resume"); 289 | isPaused = false; 290 | bindPressed = true; 291 | } 292 | } 293 | 294 | // Defines the buttons swap direction and hard reset button 295 | @Override 296 | public WWidget getWidget(GuiTheme theme) { 297 | WVerticalList list = theme.verticalList(); 298 | WHorizontalList b = list.add(theme.horizontalList()).expandX().widget(); 299 | 300 | WButton reset = b.add(theme.button("Reset progress")).expandX().widget(); 301 | reset.action = () -> { 302 | try { 303 | placedShulker = false; 304 | refilling = false; 305 | defined = false; 306 | offsetting = false; 307 | endOfLinePos = null; 308 | barPos = null; 309 | offsetPos = null; 310 | toAdvanceDir = null; 311 | length = 0; 312 | shulkerPlaceDir = toEndOfLineDir.getOpposite(); 313 | } catch (Exception e) { 314 | e.printStackTrace(); 315 | } 316 | }; 317 | 318 | return list; 319 | } 320 | 321 | @EventHandler 322 | private void onRender(Render3DEvent event) { 323 | if (renderCorners.get()) { 324 | try { 325 | Color DARKRED = new Color(139, 0, 0); 326 | event.renderer.box(cornerOne.get(), Color.RED, Color.RED, ShapeMode.Both, 0); 327 | event.renderer.box(cornerTwo.get(), DARKRED, DARKRED, ShapeMode.Both, 0); 328 | event.renderer.box(endOfLinePos, Color.BLUE, Color.BLUE, ShapeMode.Both, 0); 329 | } catch (Exception ignored) {} 330 | } 331 | } 332 | 333 | // These toggle the module if you disconnect or leave the server 334 | @EventHandler 335 | private void onScreenOpen(OpenScreenEvent event) { 336 | if (disableOnDisconnect.get() && event.screen instanceof DisconnectedScreen) toggle(); 337 | } 338 | 339 | @EventHandler 340 | private void onGameLeft(GameLeftEvent event) { 341 | if (disableOnDisconnect.get()) toggle(); 342 | } 343 | 344 | // Pathing logic 345 | private void start() { 346 | if (mc.player == null) return; 347 | 348 | currPlayerPos = mc.player.getBlockPos(); 349 | BlockPos extrapolatePos = new BlockPos(cornerOne.get().getX(), cornerOne.get().getY(), cornerTwo.get().getZ()); 350 | toEndOfLineDir = findBlockDir(cornerOne.get(), extrapolatePos); 351 | length = findDistance(cornerOne.get(), extrapolatePos, toEndOfLineDir); 352 | toAdvanceDir = findBlockDir(extrapolatePos, cornerTwo.get()); 353 | endOfLinePos = currPlayerPos.offset(toEndOfLineDir, length); 354 | barPos = currPlayerPos.offset(toEndOfLineDir, 2); 355 | shulkerPlaceDir = toEndOfLineDir.getOpposite(); 356 | defined = true; 357 | 358 | setGoal(barPos); 359 | } 360 | 361 | // Finds the direction for one block to get to the other 362 | private Direction findBlockDir(BlockPos originBlock, BlockPos goalBlock) { 363 | BlockPos vec3d = BlockPos.ofFloored(Math.signum(goalBlock.getX() - originBlock.getX()), 0, Math.signum(goalBlock.getZ() - originBlock.getZ())); 364 | return Direction.getFacing(Vec3d.of(vec3d)); 365 | } 366 | 367 | /** 368 | // Places a block below the input 369 | private void placeUnder(BlockPos pos) { 370 | if (mc.world == null) return; 371 | 372 | BlockPos under = new BlockPos(pos.offset(Direction.DOWN)); 373 | if (mc.world.getBlockState(under).isReplaceable()) { 374 | BlockUtils.place(under, InvUtils.findInHotbar(Blocks.NETHERRACK.asItem()), false, 0); 375 | } 376 | } 377 | */ 378 | 379 | private void setGoal(BlockPos goal) { 380 | baritone.getCustomGoalProcess().setGoalAndPath(new GoalBlock(goal)); 381 | } 382 | 383 | private int findDistance(BlockPos pos1, BlockPos pos2, Direction dir) { 384 | int dist = 0; 385 | switch (dir) { 386 | case NORTH, SOUTH, EAST, WEST -> dist = (int) PlayerUtils.distance(pos1.getX(), 0, pos1.getZ(), pos2.getX(), 0, pos2.getZ()); 387 | default -> {} 388 | } 389 | return dist; 390 | } 391 | 392 | // Pickaxe refilling 393 | public FindItemResult findShulkerBox() { 394 | return InvUtils.findInHotbar(itemStack -> NFUtils.shulkers.contains(itemStack.getItem())); 395 | } 396 | 397 | private void openShulker(BlockPos shulkerPos) { 398 | if (mc.interactionManager == null) return; 399 | 400 | Vec3d shulkerVec = new Vec3d(shulkerPos.getX(), shulkerPos.getY(), shulkerPos.getZ()); 401 | BlockHitResult table = new BlockHitResult(shulkerVec, Direction.UP, shulkerPos, false); 402 | mc.interactionManager.interactBlock(mc.player, Hand.MAIN_HAND, table); 403 | } 404 | 405 | private int getPickAmount() { 406 | return NFUtils.haveItem(Items.NETHERITE_PICKAXE); 407 | } 408 | 409 | private int grabAllPickaxes() { 410 | int picksMoved = 0; 411 | int availableSlots = 0; 412 | // Checks player's inventory for available slots 413 | for (int i = 27; i < mc.player.currentScreenHandler.slots.size(); i++) { 414 | Item item = mc.player.currentScreenHandler.getSlot(i).getStack().getItem(); 415 | if (item.equals(Items.AIR)) { 416 | availableSlots++; 417 | } 418 | } 419 | info("Available slots: " + availableSlots); 420 | 421 | for (int i = 0; i < mc.player.currentScreenHandler.slots.size() - 36; i++) { 422 | Item item = mc.player.currentScreenHandler.getSlot(i).getStack().getItem(); 423 | if (item.equals(Items.NETHERITE_PICKAXE)) { 424 | if (availableSlots - 2 > picksMoved) { 425 | mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, i, 1, SlotActionType.QUICK_MOVE, mc.player); 426 | picksMoved++; 427 | } 428 | } 429 | } 430 | info("Picks moved: " + picksMoved); 431 | return picksMoved; 432 | } 433 | 434 | private int getNetherrackMined() { 435 | Parser.Result result = Parser.parse("{player.get_stat(\"netherrack\",\"mined\")}"); 436 | return Integer.parseInt(String.valueOf(MeteorStarscript.ss.run(Compiler.compile(result)))); 437 | } 438 | 439 | private int getPicksBroken() { 440 | Parser.Result result = Parser.parse("{player.get_stat(\"netherite_pickaxe\",\"broken\")}"); 441 | return Integer.parseInt(String.valueOf(MeteorStarscript.ss.run(Compiler.compile(result)))); 442 | } 443 | 444 | private int getNetherrackResult() { 445 | return (finalNetherrackMined - initialNetherrackMined); 446 | } 447 | 448 | private int getPickaxesResult() { 449 | return (finalPicksBroken - initialPicksBroken); 450 | } 451 | } 452 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/modules/main/DiggingTools.java: -------------------------------------------------------------------------------- 1 | package me.redcarlos.netherfreedom.modules.main; 2 | 3 | import me.redcarlos.netherfreedom.NFAddon; 4 | import meteordevelopment.meteorclient.events.game.OpenScreenEvent; 5 | import meteordevelopment.meteorclient.events.world.TickEvent; 6 | import meteordevelopment.meteorclient.mixininterface.IVec3d; 7 | import meteordevelopment.meteorclient.settings.*; 8 | import meteordevelopment.meteorclient.systems.modules.Module; 9 | import meteordevelopment.meteorclient.systems.modules.Modules; 10 | import meteordevelopment.meteorclient.systems.modules.misc.AutoLog; 11 | import meteordevelopment.meteorclient.systems.modules.movement.AutoWalk; 12 | import meteordevelopment.meteorclient.systems.modules.movement.SafeWalk; 13 | import meteordevelopment.meteorclient.systems.modules.render.FreeLook; 14 | import meteordevelopment.meteorclient.systems.modules.world.LiquidFiller; 15 | import meteordevelopment.meteorclient.utils.player.FindItemResult; 16 | import meteordevelopment.meteorclient.utils.player.InvUtils; 17 | import meteordevelopment.orbit.EventHandler; 18 | import net.minecraft.block.Block; 19 | import net.minecraft.block.Blocks; 20 | import net.minecraft.client.gui.screen.DisconnectedScreen; 21 | import net.minecraft.item.BlockItem; 22 | import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; 23 | import net.minecraft.util.Hand; 24 | import net.minecraft.util.hit.BlockHitResult; 25 | import net.minecraft.util.math.BlockPos; 26 | import net.minecraft.util.math.Direction; 27 | import net.minecraft.util.math.MathHelper; 28 | import net.minecraft.util.math.Vec3d; 29 | 30 | import java.util.List; 31 | 32 | public class DiggingTools extends Module { 33 | private final SettingGroup sgGeneral = settings.getDefaultGroup(); 34 | private final SettingGroup sgScaffold = settings.createGroup("Scaffold"); 35 | 36 | 37 | private final Setting disableOnDisconnect = sgGeneral.add(new BoolSetting.Builder() 38 | .name("disable-on-disconnect") 39 | .description("Disables DiggingTools when you leave a server.") 40 | .defaultValue(true) 41 | .build() 42 | ); 43 | 44 | private final Setting useBaritone = sgGeneral.add(new BoolSetting.Builder() 45 | .name("(BETA)-use-baritone") 46 | .description("Use baritone to automate the digging process.") 47 | .defaultValue(false) 48 | .build() 49 | ); 50 | 51 | private final Setting scaffold = sgScaffold.add(new BoolSetting.Builder() 52 | .name("scaffold") 53 | .description("Scaffolds blocks under you.") 54 | .defaultValue(true) 55 | .build() 56 | ); 57 | 58 | private final Setting listMode = sgScaffold.add(new EnumSetting.Builder() 59 | .name("block-list-mode") 60 | .description("Block list selection mode.") 61 | .defaultValue(ListMode.Whitelist) 62 | .visible(scaffold::get) 63 | .build() 64 | ); 65 | 66 | private final Setting> whitelist = sgScaffold.add(new BlockListSetting.Builder() 67 | .name("whitelist") 68 | .description("Blocks allowed to scaffold.") 69 | .defaultValue(Blocks.NETHERRACK) 70 | .visible(() -> scaffold.get() && listMode.get() == ListMode.Whitelist) 71 | .build() 72 | ); 73 | 74 | private final Setting> blacklist = sgScaffold.add(new BlockListSetting.Builder() 75 | .name("blacklist") 76 | .description("Blocks denied to scaffold.") 77 | .defaultValue(Blocks.OBSIDIAN) 78 | .visible(() -> scaffold.get() && listMode.get() == ListMode.Blacklist) 79 | .build() 80 | ); 81 | 82 | private final Setting ext = sgScaffold.add(new IntSetting.Builder() 83 | .name("extend") 84 | .description("How much to place in front of you.") 85 | .defaultValue(3) 86 | .range(0, 5) 87 | .visible(scaffold::get) 88 | .build() 89 | ); 90 | 91 | private final Setting keepY = sgScaffold.add(new BoolSetting.Builder() 92 | .name("keep-y") 93 | .description("Places blocks only at a specific Y value.") 94 | .defaultValue(true) 95 | .visible(scaffold::get) 96 | .build() 97 | ); 98 | 99 | private final Setting height = sgScaffold.add(new IntSetting.Builder() 100 | .name("height") 101 | .description("Y value to scaffold at.") 102 | .defaultValue(120) 103 | .range(-64, 320) 104 | .sliderRange(-64, 320) 105 | .visible(() -> scaffold.get() && keepY.get()) 106 | .build() 107 | ); 108 | 109 | private final List> commonClasses = List.of( 110 | AutoLog.class, 111 | HotbarManager.class, 112 | LiquidFiller.class, 113 | NetherBorer.class, 114 | OffhandManager.class 115 | ); 116 | 117 | private final List> noBaritoneClasses = List.of( 118 | FreeLook.class, 119 | RotationNF.class, 120 | SafeWalk.class 121 | ); 122 | 123 | private final List> onDeactivateClasses = List.of( 124 | AutoWalk.class, 125 | AutoWalkNF.class, 126 | BaritoneMiner.class 127 | ); 128 | 129 | private boolean worked = false; 130 | 131 | public DiggingTools() { 132 | super(NFAddon.Main, "digging-tools", "The necessary tools to dig."); 133 | } 134 | 135 | @Override 136 | public void onActivate() { 137 | Modules modules = Modules.get(); 138 | 139 | if (useBaritone.get()) { 140 | modules.get(BaritoneMiner.class).toggle(); 141 | } else noBaritoneClasses.forEach(moduleClass -> modules.get(moduleClass).toggle()); 142 | 143 | commonClasses.forEach(moduleClass -> modules.get(moduleClass).toggle()); 144 | } 145 | 146 | @Override 147 | public void onDeactivate() { 148 | Modules modules = Modules.get(); 149 | 150 | commonClasses.stream().filter(moduleClass -> modules.get(moduleClass).isActive()).forEach(moduleClass -> modules.get(moduleClass).toggle()); 151 | noBaritoneClasses.stream().filter(moduleClass -> modules.get(moduleClass).isActive()).forEach(moduleClass -> modules.get(moduleClass).toggle()); 152 | onDeactivateClasses.stream().filter(moduleClass -> modules.get(moduleClass).isActive()).forEach(moduleClass -> modules.get(moduleClass).toggle()); 153 | } 154 | 155 | @EventHandler 156 | private void onScreenOpen(OpenScreenEvent event) { 157 | if (disableOnDisconnect.get() && event.screen instanceof DisconnectedScreen) toggle(); 158 | } 159 | 160 | @EventHandler 161 | public void onTick(TickEvent.Pre event) { 162 | if (mc.player == null || mc.world == null) return; 163 | 164 | float f = MathHelper.sin(mc.player.getYaw() * 0.017453292f); 165 | float g = MathHelper.cos(mc.player.getYaw() * 0.017453292f); 166 | 167 | for (int i = 0; i <= (mc.player.getVelocity().x == 0.0 && mc.player.getVelocity().z == 0.0 ? 0 : ext.get()); i++) { 168 | // Loop body 169 | Vec3d pos = mc.player.getPos().add(-f * i, -0.5, g * i); 170 | if (keepY.get()) ((IVec3d) pos).meteor$setY(height.get() - 1.0); 171 | 172 | BlockPos bPos = BlockPos.ofFloored(pos); 173 | 174 | if (!mc.world.getBlockState(bPos).isReplaceable()) { 175 | worked = false; 176 | continue; 177 | } 178 | worked = true; 179 | 180 | // Find slot with a block 181 | FindItemResult item; 182 | if (listMode.get() == ListMode.Whitelist) { 183 | item = InvUtils.findInHotbar(itemStack -> itemStack.getItem() instanceof BlockItem && whitelist.get().contains(Block.getBlockFromItem(itemStack.getItem()))); 184 | } else { 185 | item = InvUtils.findInHotbar(itemStack -> itemStack.getItem() instanceof BlockItem && !blacklist.get().contains(Block.getBlockFromItem(itemStack.getItem()))); 186 | } 187 | if (!item.found()) { 188 | return; 189 | } else { 190 | InvUtils.swap(item.slot(), true); 191 | } 192 | 193 | mc.player.networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(Hand.MAIN_HAND, new BlockHitResult(pos, Direction.getFacing(pos).getOpposite(), bPos, true), 0)); 194 | 195 | InvUtils.swapBack(); 196 | } 197 | } 198 | 199 | public boolean scaffoldPlaced() { 200 | return worked; 201 | } 202 | 203 | public enum ListMode { 204 | Blacklist, 205 | Whitelist 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/modules/main/HotbarManager.java: -------------------------------------------------------------------------------- 1 | package me.redcarlos.netherfreedom.modules.main; 2 | 3 | import me.redcarlos.netherfreedom.NFAddon; 4 | import meteordevelopment.meteorclient.events.world.TickEvent; 5 | import meteordevelopment.meteorclient.gui.GuiTheme; 6 | import meteordevelopment.meteorclient.gui.widgets.WWidget; 7 | import meteordevelopment.meteorclient.gui.widgets.pressable.WButton; 8 | import meteordevelopment.meteorclient.settings.*; 9 | import meteordevelopment.meteorclient.systems.modules.Module; 10 | import meteordevelopment.meteorclient.utils.player.FindItemResult; 11 | import meteordevelopment.meteorclient.utils.player.InvUtils; 12 | import meteordevelopment.meteorclient.utils.world.TickRate; 13 | import meteordevelopment.orbit.EventHandler; 14 | import net.minecraft.item.Item; 15 | import net.minecraft.item.Items; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | public class HotbarManager extends Module { 21 | private final SettingGroup sgGeneral = settings.getDefaultGroup(); 22 | 23 | private final Setting delay = sgGeneral.add(new IntSetting.Builder() 24 | .name("move-delay") 25 | .description("Delay in ticks between moving items.") 26 | .defaultValue(1) 27 | .range(1, 20) 28 | .sliderRange(1, 20) 29 | .build() 30 | ); 31 | 32 | private final Setting replace = sgGeneral.add(new BoolSetting.Builder() 33 | .name("replace") 34 | .description("Replace items already in your hotbar.") 35 | .defaultValue(true) 36 | .build() 37 | ); 38 | 39 | private final Setting toggle = sgGeneral.add(new BoolSetting.Builder() 40 | .name("toggle") 41 | .description("Toggle off automatically after one pass through the hotbar.") 42 | .defaultValue(false) 43 | .build() 44 | ); 45 | 46 | @Override 47 | public WWidget getWidget(GuiTheme theme) { 48 | WButton reset = theme.button("Reset"); 49 | reset.action = () -> itemSettings.forEach(Setting::reset); 50 | 51 | return reset; 52 | } 53 | 54 | private final List> itemSettings = new ArrayList<>(); 55 | private double ticksLeft; 56 | 57 | public HotbarManager() { 58 | super(NFAddon.Main, "hotbar-manager", "Automatically move items to your hotbar."); 59 | 60 | final SettingGroup sgHotbar = settings.createGroup("Hotbar"); 61 | 62 | for (int i = 0; i < 9; i++) { 63 | ItemSetting setting = new ItemSetting.Builder() 64 | .name("slot-" + (i + 1)) 65 | .description("The item to store in slot " + (i + 1) + ".") 66 | .defaultValue(Items.AIR) 67 | .build(); 68 | 69 | itemSettings.add(sgHotbar.add(setting)); 70 | } 71 | } 72 | 73 | @Override 74 | public void onActivate() { 75 | ticksLeft = 0.0; 76 | } 77 | 78 | @EventHandler 79 | private void onTick(TickEvent.Post event) { 80 | if (mc.player == null) return; 81 | 82 | if ((ticksLeft -= TickRate.INSTANCE.getTickRate() / 20.0) > 0.0) return; 83 | int highestSlot = -1; 84 | 85 | for (int i = 0; i < 9; i++) { 86 | if (ticksLeft > 0.0) return; 87 | highestSlot = Math.max(highestSlot, i); 88 | 89 | ItemSetting setting = (ItemSetting) itemSettings.get(i); 90 | if (setting.get() == Items.AIR) continue; 91 | 92 | Item slotItem = mc.player.getInventory().getStack(i).getItem(); 93 | if (slotItem != Items.AIR && !replace.get()) continue; 94 | if (mc.player.getInventory().getStack(i).getItem() == setting.get()) continue; 95 | 96 | FindItemResult result = InvUtils.find(stack -> stack.getItem() == setting.get(), i, 35); 97 | if (!result.found()) continue; 98 | 99 | InvUtils.move().from(result.slot()).to(i); 100 | ticksLeft = delay.get(); 101 | } 102 | 103 | if (highestSlot == 8 && toggle.get()) toggle(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/modules/main/NetherBorer.java: -------------------------------------------------------------------------------- 1 | package me.redcarlos.netherfreedom.modules.main; 2 | 3 | import me.redcarlos.netherfreedom.NFAddon; 4 | import meteordevelopment.meteorclient.events.world.TickEvent; 5 | import meteordevelopment.meteorclient.settings.IntSetting; 6 | import meteordevelopment.meteorclient.settings.Setting; 7 | import meteordevelopment.meteorclient.settings.SettingGroup; 8 | import meteordevelopment.meteorclient.systems.modules.Module; 9 | import meteordevelopment.orbit.EventHandler; 10 | import net.minecraft.block.BannerBlock; 11 | import net.minecraft.block.SignBlock; 12 | import net.minecraft.item.PickaxeItem; 13 | import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; 14 | import net.minecraft.util.Util; 15 | import net.minecraft.util.math.BlockPos; 16 | import net.minecraft.util.math.Direction; 17 | import net.minecraft.util.math.MathHelper; 18 | 19 | import java.util.stream.IntStream; 20 | 21 | import static me.redcarlos.netherfreedom.utils.NFUtils.*; 22 | 23 | public class NetherBorer extends Module { 24 | private final SettingGroup sgGeneral = settings.getDefaultGroup(); 25 | 26 | private final Setting keepY = sgGeneral.add(new IntSetting.Builder() 27 | .name("keepY") 28 | .description("Keeps a specific Y level when digging.") 29 | .defaultValue(120) 30 | .range(-1, 255) 31 | .sliderRange(-1, 255) 32 | .build() 33 | ); 34 | 35 | private int packets = 0; 36 | private long lastUpdateTime = 0; // Last time packets were sent 37 | private BlockPos playerPos = BlockPos.ORIGIN; // Floored block position of player 38 | 39 | public NetherBorer() { 40 | super(NFAddon.Main, "NF-borer", "Digs netherrack. Optimized for NetherFreedom."); 41 | } 42 | 43 | @EventHandler 44 | public void tick(TickEvent.Pre event) { 45 | if (mc.player == null || mc.world == null) return; 46 | 47 | // Previous floored block position of player 48 | BlockPos prevBlockPos = playerPos; 49 | playerPos = new BlockPos( 50 | MathHelper.floor(mc.player.getX()), 51 | keepY.get() != -1 ? keepY.get() : MathHelper.floor(mc.player.getY()), 52 | MathHelper.floor(mc.player.getZ()) 53 | ); 54 | 55 | if (playerPos != prevBlockPos || Util.getMeasuringTimeMs() - lastUpdateTime > 800) { 56 | mineArea(playerPos.add(0, 0, 0)); 57 | lastUpdateTime = Util.getMeasuringTimeMs(); 58 | } 59 | packets = 0; 60 | } 61 | 62 | protected void mineArea(BlockPos playerPos) { 63 | IntStream.rangeClosed(-4, 4).forEach(i -> { 64 | breakBlock(forward(playerPos, i)); 65 | breakBlock(forward(playerPos, i).up()); 66 | breakBlock(forward(playerPos, i).up(2)); 67 | 68 | breakBlock(right(forward(playerPos, i), 1)); 69 | breakBlock(right(forward(playerPos, i), 1).up()); 70 | breakBlock(right(forward(playerPos, i), 1).up(2)); 71 | 72 | breakBlock(right(forward(playerPos, i), 2)); 73 | breakBlock(right(forward(playerPos, i), 2).up()); 74 | breakBlock(right(forward(playerPos, i), 2).up(2)); 75 | 76 | breakBlock(right(forward(playerPos, i), 3)); 77 | breakBlock(right(forward(playerPos, i), 3).up()); 78 | breakBlock(right(forward(playerPos, i), 3).up(2)); 79 | 80 | breakBlock(right(forward(playerPos, i), 4)); 81 | breakBlock(right(forward(playerPos, i), 4).up()); 82 | breakBlock(right(forward(playerPos, i), 4).up(2)); 83 | 84 | breakBlock(left(forward(playerPos, i), 1)); 85 | breakBlock(left(forward(playerPos, i), 1).up()); 86 | breakBlock(left(forward(playerPos, i), 1).up(2)); 87 | 88 | breakBlock(left(forward(playerPos, i), 2)); 89 | breakBlock(left(forward(playerPos, i), 2).up()); 90 | breakBlock(left(forward(playerPos, i), 2).up(2)); 91 | 92 | breakBlock(left(forward(playerPos, i), 3)); 93 | breakBlock(left(forward(playerPos, i), 3).up()); 94 | breakBlock(left(forward(playerPos, i), 3).up(2)); 95 | 96 | breakBlock(left(forward(playerPos, i), 4)); 97 | breakBlock(left(forward(playerPos, i), 4).up()); 98 | breakBlock(left(forward(playerPos, i), 4).up(2)); 99 | 100 | breakBlock(backward(playerPos, i)); 101 | breakBlock(backward(playerPos, i).up()); 102 | breakBlock(backward(playerPos, i).up(2)); 103 | }); 104 | } 105 | 106 | protected void breakBlock(BlockPos blockPos) { 107 | if (mc.player == null || mc.world == null) return; 108 | 109 | // Added SignBlock and BannerBlock to preserve history :fire: 110 | if (!(mc.player.getMainHandStack().getItem() instanceof PickaxeItem) || packets >= 130 || mc.world.getBlockState(blockPos).isReplaceable() 111 | || mc.world.getBlockState(blockPos).getBlock() instanceof SignBlock 112 | || mc.world.getBlockState(blockPos).getBlock() instanceof BannerBlock) { 113 | return; 114 | } 115 | 116 | mc.player.networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, blockPos, Direction.UP)); 117 | mc.player.networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, blockPos, Direction.UP)); 118 | packets += 2; 119 | 120 | mc.player.getInventory().updateItems(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/modules/main/OffhandManager.java: -------------------------------------------------------------------------------- 1 | package me.redcarlos.netherfreedom.modules.main; 2 | 3 | import me.redcarlos.netherfreedom.NFAddon; 4 | import meteordevelopment.meteorclient.events.packets.PacketEvent; 5 | import meteordevelopment.meteorclient.events.render.Render3DEvent; 6 | import meteordevelopment.meteorclient.events.world.TickEvent; 7 | import meteordevelopment.meteorclient.settings.BoolSetting; 8 | import meteordevelopment.meteorclient.settings.IntSetting; 9 | import meteordevelopment.meteorclient.settings.Setting; 10 | import meteordevelopment.meteorclient.settings.SettingGroup; 11 | import meteordevelopment.meteorclient.systems.modules.Module; 12 | import meteordevelopment.meteorclient.systems.modules.Modules; 13 | import meteordevelopment.meteorclient.systems.modules.combat.AutoTotem; 14 | import meteordevelopment.meteorclient.utils.Utils; 15 | import meteordevelopment.meteorclient.utils.entity.EntityUtils; 16 | import meteordevelopment.meteorclient.utils.player.FindItemResult; 17 | import meteordevelopment.meteorclient.utils.player.InvUtils; 18 | import meteordevelopment.orbit.EventHandler; 19 | import net.minecraft.component.DataComponentTypes; 20 | import net.minecraft.entity.effect.StatusEffects; 21 | import net.minecraft.item.Items; 22 | import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; 23 | import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; 24 | import net.minecraft.util.Hand; 25 | import net.minecraft.util.math.Direction; 26 | 27 | public class OffhandManager extends Module { 28 | private final SettingGroup sgGeneral = settings.getDefaultGroup(); 29 | private final SettingGroup sgAutoGap = settings.createGroup("Auto Gap"); 30 | private final SettingGroup sgAutoTotem = settings.createGroup("Auto Totem"); 31 | 32 | private final Setting hotbar = sgGeneral.add(new BoolSetting.Builder() 33 | .name("hotbar") 34 | .description("Whether to use items from your hotbar.") 35 | .defaultValue(true) 36 | .build() 37 | ); 38 | 39 | private final Setting warningMsg = sgGeneral.add(new BoolSetting.Builder() 40 | .name("notify") 41 | .description("Warns you when the selected item is not found in your inventory.") 42 | .defaultValue(false) 43 | .build() 44 | ); 45 | 46 | // Auto Gap 47 | 48 | private final Setting hungerThreshold = sgAutoGap.add(new IntSetting.Builder() 49 | .name("hunger") 50 | .description("Hunger to gap at.") 51 | .defaultValue(16) 52 | .range(1, 19) 53 | .sliderRange(1, 19) 54 | .build() 55 | ); 56 | 57 | private final Setting autoFireRes = sgAutoGap.add(new BoolSetting.Builder() 58 | .name("fire-resistance") 59 | .description("Gap when no fire resistance effect.") 60 | .defaultValue(true) 61 | .build() 62 | ); 63 | 64 | // Auto Totem 65 | 66 | private final Setting healthThreshold = sgAutoTotem.add(new IntSetting.Builder() 67 | .name("min-health") 68 | .description("The minimum health to hold a totem at.") 69 | .defaultValue(6) 70 | .range(0, 35) 71 | .sliderMax(35) 72 | .build() 73 | ); 74 | 75 | private final Setting fallDamage = sgAutoTotem.add(new BoolSetting.Builder() 76 | .name("fall-damage") 77 | .description("Holds a totem when fall damage could kill you.") 78 | .defaultValue(true) 79 | .build() 80 | ); 81 | 82 | private Item currentItem; 83 | private boolean eating; 84 | private boolean justStarted; 85 | private boolean moved; 86 | private boolean sentMsg; 87 | private boolean swapped; 88 | 89 | public OffhandManager() { 90 | super(NFAddon.Main, "hand-manager", "Automatically manages your offhand. Optimized for NetherFreedom."); 91 | } 92 | 93 | @Override 94 | public void onActivate() { 95 | eating = false; 96 | justStarted = true; 97 | moved = false; 98 | sentMsg = false; 99 | swapped = true; 100 | currentItem = Item.Totem; 101 | } 102 | 103 | @Override 104 | public void onDeactivate() { 105 | if (eating) stopEating(); 106 | } 107 | 108 | @EventHandler 109 | public void onRender3D(Render3DEvent event) { 110 | if (mc.player == null || mc.world == null) return; 111 | if (!Utils.canUpdate()) return; 112 | 113 | // Anti cursor stack 114 | if (moved) { 115 | InvUtils.dropHand(); 116 | moved = false; 117 | } 118 | 119 | Modules modules = Modules.get(); 120 | AutoTotem autoTotem = modules.get(AutoTotem.class); 121 | if (Modules.get().get(DiggingTools.class).scaffoldPlaced()) return; 122 | 123 | // Switch back if swap key has been used 124 | if (mc.options.swapHandsKey.isPressed() && !swapped && mc.player.getOffHandStack().getItem() == currentItem.item) swapped = true; 125 | else if (mc.options.swapHandsKey.isPressed() && swapped && mc.player.getMainHandStack().getItem() == currentItem.item) swapped = false; 126 | else swapped = false; 127 | 128 | // Checking offhand item 129 | if (mc.player.getOffHandStack().getItem() != currentItem.item && !swapped) { 130 | FindItemResult item = InvUtils.find(itemStack -> itemStack.getItem() == currentItem.item, hotbar.get() ? 0 : 9, 35); 131 | 132 | if (!item.found()) { 133 | if (!sentMsg) { 134 | if (warningMsg.get()) warning("Chosen item not found."); 135 | sentMsg = true; 136 | moved = false; 137 | } 138 | } 139 | 140 | // Swap to offhand 141 | else if (!autoTotem.isLocked() && !item.isOffhand()) { 142 | InvUtils.move().from(item.slot()).toOffhand(); 143 | sentMsg = false; 144 | moved = true; 145 | } 146 | } 147 | } 148 | 149 | @EventHandler 150 | private void onPreTick(TickEvent.Pre event) { 151 | if (mc.player == null) return; 152 | 153 | if (eating) { 154 | // If we are eating check if we should still be eating 155 | if (shouldEat()) { 156 | // Check if the item in current slot is not an egap 157 | if (mc.player.getOffHandStack().getComponents().get(DataComponentTypes.FOOD) == null) { 158 | stopEating(); 159 | } else { 160 | startEating(); 161 | } 162 | } else { 163 | stopEating(); // If we shouldn't be eating anymore then stop 164 | } 165 | } else { 166 | // If we are not eating check if we should start eating 167 | if (shouldEat() && mc.player.getOffHandStack().getComponents().get(DataComponentTypes.FOOD) != null) { 168 | startEating(); 169 | } 170 | } 171 | } 172 | 173 | @EventHandler 174 | private void onPostTick(TickEvent.Post event) { 175 | if (mc.player == null || mc.world == null) return; 176 | 177 | if (mc.player.getHealth() <= healthThreshold.get() || fallDamage.get() && !EntityUtils.isAboveWater(mc.player) && mc.player.fallDistance > 3) currentItem = Item.Totem; 178 | else if (autoFireRes.get() && !justStarted && !mc.player.getActiveStatusEffects().containsKey(StatusEffects.FIRE_RESISTANCE)) currentItem = Item.EGap; 179 | else if (mc.player.getHungerManager().getFoodLevel() < hungerThreshold.get() + 1) currentItem = Item.EGap; 180 | else currentItem = Item.Totem; 181 | } 182 | 183 | @EventHandler 184 | public void onReceivePacket(PacketEvent.Receive event) { 185 | if (event.packet instanceof PlayerInteractBlockC2SPacket) stopEating(); 186 | } 187 | 188 | private boolean shouldEat() { 189 | return (mc.player.getHungerManager().getFoodLevel() <= hungerThreshold.get() || autoFireRes.get() && !mc.player.getActiveStatusEffects().containsKey(StatusEffects.FIRE_RESISTANCE)) && !Modules.get().get(DiggingTools.class).scaffoldPlaced(); 190 | } 191 | 192 | private void startEating() { 193 | if (mc.player == null || mc.interactionManager == null) return; 194 | 195 | eating = true; 196 | justStarted = false; 197 | 198 | if (mc.player.isUsingItem()) return; 199 | 200 | mc.options.useKey.setPressed(true); 201 | mc.interactionManager.interactItem(mc.player, Hand.OFF_HAND); 202 | } 203 | 204 | private void stopEating() { 205 | if (mc.player == null) return; 206 | 207 | mc.options.useKey.setPressed(false); 208 | mc.player.stopUsingItem(); 209 | mc.player.networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.RELEASE_USE_ITEM, mc.player.getBlockPos(), Direction.DOWN)); 210 | eating = false; 211 | } 212 | 213 | public boolean isEating() { 214 | return isActive() && eating; 215 | } 216 | 217 | public enum Item { 218 | EGap(Items.ENCHANTED_GOLDEN_APPLE), 219 | Totem(Items.TOTEM_OF_UNDYING); 220 | 221 | final net.minecraft.item.Item item; 222 | 223 | Item(net.minecraft.item.Item item) { 224 | this.item = item; 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/modules/main/RotationNF.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). 3 | * Copyright (c) Meteor Development. 4 | * Enhanced by RedCarlos26 5 | */ 6 | 7 | package me.redcarlos.netherfreedom.modules.main; 8 | 9 | import me.redcarlos.netherfreedom.NFAddon; 10 | import meteordevelopment.meteorclient.events.game.GameLeftEvent; 11 | import meteordevelopment.meteorclient.events.game.OpenScreenEvent; 12 | import meteordevelopment.meteorclient.events.world.TickEvent; 13 | import meteordevelopment.meteorclient.settings.*; 14 | import meteordevelopment.meteorclient.systems.modules.Module; 15 | import meteordevelopment.meteorclient.utils.misc.input.Input; 16 | import meteordevelopment.orbit.EventHandler; 17 | import net.minecraft.client.gui.screen.DisconnectedScreen; 18 | import org.lwjgl.glfw.GLFW; 19 | 20 | public class RotationNF extends Module { 21 | private final SettingGroup sgYaw = settings.createGroup("Yaw"); 22 | private final SettingGroup sgPitch = settings.createGroup("Pitch"); 23 | 24 | // Yaw 25 | 26 | private final Setting yawLockMode = sgYaw.add(new EnumSetting.Builder() 27 | .name("yaw-lock-mode") 28 | .description("The way in which your yaw is locked.") 29 | .defaultValue(LockMode.Smart) 30 | .build() 31 | ); 32 | 33 | private final Setting yawAngle = sgYaw.add(new DoubleSetting.Builder() 34 | .name("yaw-angle") 35 | .description("Yaw angle in degrees.") 36 | .defaultValue(0) 37 | .sliderMax(360) 38 | .max(360) 39 | .visible(() -> yawLockMode.get() == LockMode.Simple) 40 | .build() 41 | ); 42 | 43 | private final Setting arrowSnap = sgYaw.add(new BoolSetting.Builder() 44 | .name("arrows-snap") 45 | .description("Snap your player at 45° steps with the arrow keys.") 46 | .visible(() -> yawLockMode.get() != LockMode.None) 47 | .build() 48 | ); 49 | 50 | // Pitch 51 | 52 | private final Setting pitchLockMode = sgPitch.add(new EnumSetting.Builder() 53 | .name("pitch-lock-mode") 54 | .description("The way in which your pitch is locked.") 55 | .defaultValue(LockMode.None) 56 | .build() 57 | ); 58 | 59 | private final Setting pitchAngle = sgPitch.add(new DoubleSetting.Builder() 60 | .name("pitch-angle") 61 | .description("Pitch angle in degrees.") 62 | .defaultValue(0) 63 | .range(-90, 90) 64 | .sliderRange(-90, 90) 65 | .visible(() -> pitchLockMode.get() == LockMode.Simple) 66 | .build() 67 | ); 68 | 69 | private boolean lDown, rDown; 70 | 71 | public RotationNF() { 72 | super(NFAddon.Main, "rotation-NF", "Changes/locks your yaw and pitch."); 73 | } 74 | 75 | @Override 76 | public void onActivate() { 77 | lDown = false; 78 | rDown = false; 79 | } 80 | 81 | @EventHandler 82 | private void onScreenOpen(OpenScreenEvent event) { 83 | if (event.screen instanceof DisconnectedScreen) { 84 | toggle(); 85 | } 86 | } 87 | 88 | @EventHandler 89 | private void onGameLeft(GameLeftEvent event) { 90 | toggle(); 91 | } 92 | 93 | @EventHandler 94 | private void onTick(TickEvent.Post event) { 95 | if (mc.player == null || mc.world == null) return; 96 | 97 | switch (yawLockMode.get()) { 98 | case Simple -> setYawAngle(yawAngle.get().floatValue()); 99 | case Smart -> setYawAngle(Math.round((mc.player.getYaw() + 1f) / 45f) * 45f); 100 | } 101 | 102 | switch (pitchLockMode.get()) { 103 | case Simple -> mc.player.setPitch(pitchAngle.get().floatValue()); 104 | case Smart -> mc.player.setPitch(Math.round(((mc.player.getPitch() + 1f) / 30f) * 30f)); 105 | } 106 | 107 | if (arrowSnap.get() && yawLockMode.get() != LockMode.None) { 108 | if (!Input.isKeyPressed(GLFW.GLFW_KEY_LEFT)) lDown = false; 109 | 110 | if (Input.isKeyPressed(GLFW.GLFW_KEY_LEFT) && !lDown) { 111 | mc.player.setYaw(mc.player.getYaw() - 45); 112 | lDown = true; 113 | return; 114 | } 115 | 116 | if (!Input.isKeyPressed(GLFW.GLFW_KEY_RIGHT)) rDown = false; 117 | 118 | if (Input.isKeyPressed(GLFW.GLFW_KEY_RIGHT) && !rDown) { 119 | mc.player.setYaw(mc.player.getYaw() + 45); 120 | rDown = true; 121 | } 122 | } 123 | } 124 | 125 | private void setYawAngle(float yawAngle) { 126 | if (mc.player == null || mc.world == null) return; 127 | 128 | mc.player.setYaw(yawAngle); 129 | mc.player.headYaw = yawAngle; 130 | mc.player.bodyYaw = yawAngle; 131 | } 132 | 133 | public enum LockMode { 134 | Smart, 135 | Simple, 136 | None 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/me/redcarlos/netherfreedom/utils/NFUtils.java: -------------------------------------------------------------------------------- 1 | package me.redcarlos.netherfreedom.utils; 2 | 3 | import it.unimi.dsi.fastutil.ints.Int2IntMap; 4 | import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; 5 | import net.minecraft.item.Item; 6 | import net.minecraft.item.Items; 7 | import net.minecraft.util.math.BlockPos; 8 | 9 | import java.util.ArrayList; 10 | import java.util.stream.IntStream; 11 | 12 | import static meteordevelopment.meteorclient.MeteorClient.mc; 13 | 14 | public class NFUtils { 15 | private NFUtils() {} 16 | 17 | // Packets 18 | 19 | private static final Int2IntMap packetToClient = new Int2IntOpenHashMap(); 20 | private static final Int2IntMap clientToPacket = new Int2IntOpenHashMap(); 21 | 22 | static { 23 | packetToClient.put(5, 39); 24 | clientToPacket.put(39, 5); 25 | packetToClient.put(6, 38); 26 | clientToPacket.put(38, 6); 27 | packetToClient.put(7, 37); 28 | clientToPacket.put(37, 7); 29 | packetToClient.put(8, 36); 30 | clientToPacket.put(36, 8); 31 | packetToClient.put(45, 40); 32 | clientToPacket.put(40, 45); 33 | IntStream.rangeClosed(9, 35).forEach(i -> { 34 | packetToClient.put(i, i); 35 | clientToPacket.put(i, i); 36 | }); 37 | IntStream.rangeClosed(0, 8).forEach(i -> { 38 | packetToClient.put(i + 36, i); 39 | clientToPacket.put(i, i + 36); 40 | }); 41 | } 42 | 43 | public static int csToPs(int clientSlot) { 44 | return clientToPacket.getOrDefault(clientSlot, -1); 45 | } 46 | 47 | // BlockPos 48 | 49 | public static BlockPos forward(BlockPos pos, int distance) { 50 | return switch (mc.player.getHorizontalFacing()) { 51 | case SOUTH -> pos.south(distance); 52 | case NORTH -> pos.north(distance); 53 | case WEST -> pos.west(distance); 54 | default -> pos.east(distance); 55 | }; 56 | } 57 | 58 | public static BlockPos backward(BlockPos pos, int distance) { 59 | return switch (mc.player.getHorizontalFacing()) { 60 | case SOUTH -> pos.north(distance); 61 | case NORTH -> pos.south(distance); 62 | case WEST -> pos.east(distance); 63 | default -> pos.west(distance); 64 | }; 65 | } 66 | 67 | public static BlockPos left(BlockPos pos, int distance) { 68 | return switch (mc.player.getHorizontalFacing()) { 69 | case SOUTH -> pos.east(distance); 70 | case NORTH -> pos.west(distance); 71 | case WEST -> pos.south(distance); 72 | default -> pos.north(distance); 73 | }; 74 | } 75 | 76 | public static BlockPos right(BlockPos pos, int distance) { 77 | return switch (mc.player.getHorizontalFacing()) { 78 | case SOUTH -> pos.west(distance); 79 | case NORTH -> pos.east(distance); 80 | case WEST -> pos.north(distance); 81 | default -> pos.south(distance); 82 | }; 83 | } 84 | 85 | // Other 86 | 87 | public static int haveItem(Item item) { 88 | int count = 0; 89 | for (int i = 0; i < mc.player.getInventory().main.size(); i++) { 90 | if (mc.player.getInventory().getStack(i).getItem() == item) { 91 | count++; 92 | } 93 | } 94 | return count; 95 | } 96 | 97 | public static ArrayList shulkers = new ArrayList<>(){{ 98 | add(Items.SHULKER_BOX); 99 | add(Items.BLACK_SHULKER_BOX); 100 | add(Items.BLUE_SHULKER_BOX); 101 | add(Items.BROWN_SHULKER_BOX); 102 | add(Items.CYAN_SHULKER_BOX); 103 | add(Items.GRAY_SHULKER_BOX); 104 | add(Items.GREEN_SHULKER_BOX); 105 | add(Items.LIGHT_BLUE_SHULKER_BOX); 106 | add(Items.LIGHT_GRAY_SHULKER_BOX); 107 | add(Items.LIME_SHULKER_BOX); 108 | add(Items.MAGENTA_SHULKER_BOX); 109 | add(Items.ORANGE_SHULKER_BOX); 110 | add(Items.PINK_SHULKER_BOX); 111 | add(Items.PURPLE_SHULKER_BOX); 112 | add(Items.RED_SHULKER_BOX); 113 | add(Items.WHITE_SHULKER_BOX); 114 | add(Items.YELLOW_SHULKER_BOX); 115 | }}; 116 | } 117 | -------------------------------------------------------------------------------- /src/main/resources/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PoopenfartenDevelopment/NetherFreedom-Addon/0f6063c178d68e59f05257c5a00588f87de47ab2/src/main/resources/assets/icon.png -------------------------------------------------------------------------------- /src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "name": "NF Addon", 4 | "id": "nfaddon", 5 | "version": "${version}", 6 | "description": "Nether Freedom Project's custom meteor addon to dig netherrack.", 7 | "authors": [ 8 | "RedCarlos26", 9 | "Ethius", 10 | "Yeetusthefeetus" 11 | 12 | ], 13 | "contact": { 14 | "homepage": "https://github.com/PoopenfartenDevelopment/NetherFreedom-Addon" 15 | }, 16 | "icon": "assets/icon.png", 17 | "environment": "client", 18 | "entrypoints": { 19 | "meteor": [ 20 | "me.redcarlos.netherfreedom.NFAddon" 21 | ] 22 | }, 23 | "mixins": [ 24 | ], 25 | "accessWidener": "netherfreedom.accesswidener", 26 | "custom": { 27 | "meteor-client:color": "145,61,226" 28 | }, 29 | "depends": { 30 | "java": ">=21", 31 | "minecraft": "${minecraft_version}", 32 | "fabricloader": ">=${loader_version}", 33 | "meteor-client": ">=${minecraft_version}-9", 34 | "baritone-meteor": "${minecraft_version}-SNAPSHOT" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/resources/netherfreedom.accesswidener: -------------------------------------------------------------------------------- 1 | accessWidener v1 named 2 | 3 | 4 | accessible method net/minecraft/client/network/ClientPlayerInteractionManager syncSelectedSlot ()V 5 | --------------------------------------------------------------------------------