commit d44985347f21fdf22477abe7028e3cb68fa435df Author: Patrick <147879351+WinniePatGG@users.noreply.github.com> Date: Fri May 1 19:12:47 2026 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5f737e --- /dev/null +++ b/.gitignore @@ -0,0 +1,119 @@ +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Cache of project +.gradletasknamecache + +**/build/ + +# Common working directory +run/ +runs/ + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..84e91dc --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,2 @@ +Copyright (c) 2025 onyxx +All rights reserved. diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..9a1bf58 --- /dev/null +++ b/build.gradle @@ -0,0 +1,76 @@ +plugins { + id 'fabric-loom' version '1.9-SNAPSHOT' + id 'maven-publish' +} + +version = project.mod_version +group = project.maven_group + +base { + archivesName = project.archives_base_name +} + + +repositories { + maven { url = "https://maven.fabricmc.net/" } + maven { url = 'https://maven.wispforest.io/releases/' } + maven { url = 'https://repo.u-team.info' } +} + +dependencies { + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + implementation 'org.reflections:reflections:0.10.2' + + modImplementation 'org.reflections:reflections:0.10.2' + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" +} + +processResources { + inputs.property "version", project.version + inputs.property "minecraft_version", project.minecraft_version + inputs.property "loader_version", project.loader_version + filteringCharset "UTF-8" + + filesMatching("fabric.mod.json") { + expand "version": project.version, + "minecraft_version": project.minecraft_version, + "loader_version": project.loader_version + } +} + +def targetJavaVersion = 21 +tasks.withType(JavaCompile).configureEach { + it.options.encoding = "UTF-8" + if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { + it.options.release.set(targetJavaVersion) + } +} + +java { + def javaVersion = JavaVersion.toVersion(targetJavaVersion) + if (JavaVersion.current() < javaVersion) { + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + } + withSourcesJar() +} + +jar { + from("LICENSE") { + rename { "${it}_${project.archivesBaseName}" } + } +} + +publishing { + publications { + create("mavenJava", MavenPublication) { + artifactId = project.archives_base_name + from components.java + } + } + + repositories { + + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..0ba1a29 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,14 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G +# Fabric Properties +# check these on https://modmuss50.me/fabric.html +minecraft_version=1.21.4 +yarn_mappings=1.21.4+build.8 +loader_version=0.16.10 +# Mod Properties +mod_version=1.2 +maven_group=online.bobtony +archives_base_name=BobTony +# Dependencies +# check this on https://modmuss50.me/fabric.html +fabric_version=0.115.1+1.21.4 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..a4b76b9 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e2847c8 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..f5feea6 --- /dev/null +++ b/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 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. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + 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. +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=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# 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" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# 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, 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 \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9d21a21 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@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 ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +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 + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +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 %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..f91a4fe --- /dev/null +++ b/settings.gradle @@ -0,0 +1,9 @@ +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + } +} diff --git a/src/main/java/online/bobtony/BobTony.java b/src/main/java/online/bobtony/BobTony.java new file mode 100644 index 0000000..a2638ab --- /dev/null +++ b/src/main/java/online/bobtony/BobTony.java @@ -0,0 +1,240 @@ +package online.bobtony; + +import com.mojang.blaze3d.systems.RenderSystem; +import online.bobtony.handlers.*; +import online.bobtony.gui.Color; +import online.bobtony.utils.render.Render3D; +import online.bobtony.enums.Modes; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.block.*; +import net.minecraft.block.entity.*; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.render.*; +import net.minecraft.client.util.InputUtil; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.text.Text; +import net.minecraft.util.math.*; +import net.minecraft.world.World; +import net.minecraft.world.chunk.WorldChunk; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.glfw.GLFW; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +public class BobTony { + public static KeyBinding toggleModeKey = null; + public static KeyBinding overlayEditor = null; + + public static final String PREFIX = "§8[§6BobTony§8] §r"; + + public static List trackerList = new ArrayList<>(); + public static long lastUpdateTime = System.currentTimeMillis(); + public static long lastJumpTime = 0; + public static boolean wasJumping = false; + public static long lastModeSwitchTime = 0; + public static final long MODE_SWITCH_COOLDOWN = 1000; + public static float flyspeed = 0.1f; + public static float strength = 2.0f; + public static float speed = 1.0f; + public static boolean nofall = false; + public static Modes mode = Modes.NONE; + public List trackerBlockList = new ArrayList<>(); + public static boolean chestesp = false; + public static boolean fly = false; + public static volatile int hashesPerSecond = 0; + + public BobTony() { + toggleModeKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( + "bobtony.switchmodes", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_M, + "BobTony" + )); + + overlayEditor = KeyBindingHelper.registerKeyBinding(new KeyBinding( + "bobtony.overlayeditor", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_RIGHT_SHIFT, + "BobTony" + )); + + ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (client.player == null) return; + ClientPlayerEntity player = client.player; + ModeSwitchHandler.handleModeSwitch(player); + DoubleJumpHandler.handleDoubleJump(player); + + if (nofall && client.player != null && !client.player.getAbilities().flying) { + client.getNetworkHandler().sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround( + client.player.getX(), + client.player.getY(), + client.player.getZ(), + true, + false + )); + client.player.fallDistance = 0.0f; + } + + }); + + ClientSendMessageEvents.ALLOW_CHAT.register(message -> { + if (message.startsWith(".strength ")){ + StrengthCommandHandler.handleStrengthCommand(message); + return false; + }else if (message.equals(".nofall")) { + NoFallCommandHandler.handelNoFallCommand(); + return false; + } else if (message.startsWith(".flyspeed ")) { + FlySpeedCommandHandler.handelFlySpeedCommand(message); + return false; + } else if (message.equals(".nukeserver")) { + NukeCommandHandler.handleNukeCommand(); + return false; + } else if (message.startsWith(".speed ")) { + SpeedCommandHandler.handleSpeedCommand(message); + return false; + } else if (message.startsWith(".tracker ")) { + TrackerHandler.handleTracker(message); + return false; + } else if (message.equals(".chestesp")) { + ChestESPHandler.handleChestESP(); + return false; + } else if (message.equals(".fly")){ + FlyHandler.handleFly(); + return false; + } + + return true; + }); + + WorldRenderEvents.AFTER_ENTITIES.register(context -> { + MinecraftClient client = MinecraftClient.getInstance(); + MatrixStack matrices = context.matrixStack(); + VertexConsumerProvider vertexConsumer = context.consumers(); + Vec3d cameraPos = client.gameRenderer.getCamera().getPos(); + World world = client.world; + + float tickDelta = context.tickCounter().getTickDelta(false); + Color color = new Color(255, 0, 0, 1.0F); + + for (Entity entity : client.world.getEntities()) { + if (trackerList != null) { + for (String name : trackerList) { + if (Objects.equals(entity.getName(), Text.literal(name))) { + Render3D.drawLineToEntity(matrices, client.player, entity, tickDelta, color, 2.0f); + if (entity != client.player) { + double interpolatedX = entity.prevX + (entity.getX() - entity.prevX) * tickDelta; + double interpolatedY = entity.prevY + (entity.getY() - entity.prevY) * tickDelta; + double interpolatedZ = entity.prevZ + (entity.getZ() - entity.prevZ) * tickDelta; + + Box box = entity.getBoundingBox().offset( + interpolatedX - entity.getX() - cameraPos.x, + interpolatedY - entity.getY() - cameraPos.y, + interpolatedZ - entity.getZ() - cameraPos.z + ); + + Render3D.draw3DHitBox(matrices, box, color, 2.0F); + } + } + } + } + } + + if (chestesp){ + getTileEntities().forEach(blockEntity -> + { + Box box = new Box( + blockEntity.getPos().getX() - cameraPos.x, + blockEntity.getPos().getY() - cameraPos.y, + blockEntity.getPos().getZ() - cameraPos.z, + blockEntity.getPos().getX() + 1 - cameraPos.x, + blockEntity.getPos().getY() + 1 - cameraPos.y, + blockEntity.getPos().getZ() + 1 - cameraPos.z + ); + if (blockEntity instanceof ChestBlockEntity || blockEntity instanceof TrappedChestBlockEntity) { + Color blockColor = new Color(0, 255, 0, 1.0F); + Render3D.draw3DBox(matrices, box, blockColor, 2.0F); + Render3D.drawLineToBlockEntity(matrices, client.player, blockEntity, tickDelta, blockColor, 2.0f); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + }else if (blockEntity instanceof BarrelBlockEntity){ + Color blockColor = new Color(0, 0, 255, 1.0F); + Render3D.draw3DBox(matrices, box, blockColor, 2.0F); + Render3D.drawLineToBlockEntity(matrices, client.player, blockEntity, tickDelta, blockColor, 2.0f); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + }else if (blockEntity instanceof FurnaceBlockEntity){ + Color blockColor = new Color(255, 0, 0, 1.0F); + Render3D.draw3DBox(matrices, box, blockColor, 2.0F); + Render3D.drawLineToBlockEntity(matrices, client.player, blockEntity, tickDelta, blockColor, 2.0f); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + }else if (blockEntity instanceof ShulkerBoxBlockEntity){ + Color blockColor = new Color(255, 100, 0, 1.0F); + Render3D.draw3DBox(matrices, box, blockColor, 2.0F); + Render3D.drawLineToBlockEntity(matrices, client.player, blockEntity, tickDelta, blockColor, 2.0f); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + }else if (blockEntity instanceof BeaconBlockEntity){ + Color blockColor = new Color(0, 255, 255, 1.0F); + Render3D.draw3DBox(matrices, box, blockColor, 2.0F); + Render3D.drawLineToBlockEntity(matrices, client.player, blockEntity, tickDelta, blockColor, 2.0f); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + }else if (blockEntity instanceof DropperBlockEntity){ + Color blockColor = new Color(255, 255, 0, 1.0F); + Render3D.draw3DBox(matrices, box, blockColor, 2.0F); + Render3D.drawLineToBlockEntity(matrices, client.player, blockEntity, tickDelta, blockColor, 2.0f); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + } else if (blockEntity instanceof DispenserBlockEntity) { + Color blockColor = new Color(255, 255, 255, 1.0F); + Render3D.draw3DBox(matrices, box, blockColor, 2.0F); + Render3D.drawLineToBlockEntity(matrices, client.player, blockEntity, tickDelta, blockColor, 2.0f); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + } else if (blockEntity instanceof EnderChestBlockEntity){ + Color blockColor = new Color(255, 0, 255, 1.0F); + Render3D.draw3DBox(matrices, box, blockColor, 2.0F); + Render3D.drawLineToBlockEntity(matrices, client.player, blockEntity, tickDelta, blockColor, 2.0f); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + } + }); + } + }); + } + + public static Stream getTileEntities() { + return getLoadedChunks().flatMap(chunk -> chunk.getBlockEntities().values().stream()); + } + + public static Stream getLoadedChunks() { + int radius = Math.max(2, MinecraftClient.getInstance().options.getClampedViewDistance()) + 3; + int diameter = radius * 2 + 1; + + ChunkPos center = MinecraftClient.getInstance().player.getChunkPos(); + ChunkPos min = new ChunkPos(center.x - radius, center.z - radius); + ChunkPos max = new ChunkPos(center.x + radius, center.z + radius); + + Stream stream = Stream.iterate(min, pos -> { + int x = pos.x; + int z = pos.z; + x++; + + if (x > max.x) { + x = min.x; + z++; + } + return new ChunkPos(x, z); + }).limit((long) diameter * diameter).filter(c -> MinecraftClient.getInstance().world.isChunkLoaded(c.x, c.z)).map(c -> MinecraftClient.getInstance().world.getChunk(c.x, c.z)).filter(Objects::nonNull); + + return stream; + } + + public static void sendMessage(@NotNull ClientPlayerEntity player,@NotNull String message, boolean overlay) { + player.sendMessage(Text.literal(PREFIX + message), overlay); + } +} \ No newline at end of file diff --git a/src/main/java/online/bobtony/BobtonyClient.java b/src/main/java/online/bobtony/BobtonyClient.java new file mode 100644 index 0000000..9f4600f --- /dev/null +++ b/src/main/java/online/bobtony/BobtonyClient.java @@ -0,0 +1,19 @@ +package online.bobtony; + +import net.fabricmc.api.ClientModInitializer; +import net.minecraft.client.MinecraftClient; + + +public class BobtonyClient implements ClientModInitializer { + private static MinecraftClient instance; + + @Override + public void onInitializeClient() { + instance = MinecraftClient.getInstance(); + new BobTony(); + } + + public static MinecraftClient getInstance() { + return instance; + } +} \ No newline at end of file diff --git a/src/main/java/online/bobtony/enums/Modes.java b/src/main/java/online/bobtony/enums/Modes.java new file mode 100644 index 0000000..b734116 --- /dev/null +++ b/src/main/java/online/bobtony/enums/Modes.java @@ -0,0 +1,7 @@ +package online.bobtony.enums; + +public enum Modes { + + FLY, BOOST, NONE + +} diff --git a/src/main/java/online/bobtony/gui/Color.java b/src/main/java/online/bobtony/gui/Color.java new file mode 100644 index 0000000..1d53c98 --- /dev/null +++ b/src/main/java/online/bobtony/gui/Color.java @@ -0,0 +1,271 @@ +package online.bobtony.gui; + +import org.apache.commons.lang3.StringUtils; +import org.joml.Vector3f; + +public class Color { + private int r; + private int g; + private int b; + private int alpha = 255; + + private float hue; + private float saturation; + private float luminance; + + public Color(int r, int g, int b) { + this.r = r; + this.g = g; + this.b = b; + + HSVFromRGB(r, g, b); + } + + public Color(int r, int g, int b, int alpha) { + this.r = r; + this.g = g; + this.b = b; + + HSVFromRGB(r, g, b); + + this.alpha = alpha; + } + + public Color(float r, float g, float b, float alpha) { + this.r = (int) (r * 255f); + this.g = (int) (g * 255f); + this.b = (int) (b * 255f); + this.alpha = (int) (alpha * 255f); + } + + public Color getAsSolid() { + return new Color(r, g, b, 255); + } + + public static Color interpolate(Color color1, Color color2, float factor) { + int r = (int) (color1.r + (color2.r - color1.r) * factor); + int g = (int) (color1.g + (color2.g - color1.g) * factor); + int b = (int) (color1.b + (color2.b - color1.b) * factor); + int alpha = (int) (color1.alpha + (color2.alpha - color1.alpha) * factor); + return new Color(r, g, b, alpha); + } + + private void HSVFromRGB(int r, int g, int b) { + float rPrime = r / 255.0f; + float gPrime = g / 255.0f; + float bPrime = b / 255.0f; + + float cMax = Math.max(rPrime, Math.max(gPrime, bPrime)); + float cMin = Math.min(rPrime, Math.min(gPrime, bPrime)); + + float delta = cMax - cMin; + + if (delta == 0.0f) { + hue = 0.0f; + } else { + if (cMax == rPrime) { + hue = (60.0f * (((gPrime - bPrime) / delta) % 6)); + } else if (cMax == gPrime) { + hue = (60.0f * (((bPrime - rPrime) / delta) + 2)); + } else if (cMax == bPrime) { + hue = (60.0f * (((rPrime - gPrime) / delta) + 2)); + } + } + + if (cMax == 0.0f) + saturation = 0.0f; + else + saturation = delta / cMax; + + luminance = cMax; + } + + public Color(float hue, float saturation, float luminance) { + this.setHSV(hue, saturation, luminance); + } + + public float getHue() { + return hue; + } + + public float getSaturation() { + return saturation; + } + + public float getLuminance() { + return luminance; + } + + public void setHSV(float hue, float saturation, float luminance) { + this.hue = hue; + this.saturation = saturation; + this.luminance = luminance; + Color vec = hsv2rgb(hue, saturation, luminance); + if (vec != null) { + this.r = vec.r; + this.g = vec.g; + this.b = vec.b; + } + } + + public void setHue(float hue) { + this.hue = hue; + Color vec = hsv2rgb(this.hue, this.saturation, this.luminance); + if (vec != null) { + this.r = vec.r; + this.g = vec.g; + this.b = vec.b; + } + } + + public void setSaturation(float saturation) { + this.saturation = saturation; + Color vec = hsv2rgb(this.hue, this.saturation, this.luminance); + if (vec != null) { + this.r = vec.r; + this.g = vec.g; + this.b = vec.b; + } + } + + public void setLuminance(float luminance) { + this.luminance = luminance; + Color vec = hsv2rgb(this.hue, this.saturation, this.luminance); + if (vec != null) { + this.r = vec.r; + this.g = vec.g; + this.b = vec.b; + } + } + + public void setRGB(int r, int g, int b) { + this.r = r; + this.g = g; + this.b = b; + } + + public void setRGBA(int r, int g, int b, int alpha) { + this.r = r; + this.g = b; + this.b = b; + this.alpha = alpha; + } + + public void setAlpha(int alpha) { + this.alpha = alpha; + } + + public String getColorAsString() { + String rs = Integer.toString((int) (r)); + String gs = Integer.toString((int) (g)); + String bs = Integer.toString((int) (b)); + return rs + gs + bs; + } + + public int getColorAsInt() { + int Alpha = ((this.alpha) << 24) & 0xFF000000; + int R = ((this.r) << 16) & 0x00FF0000; + int G = ((this.g) << 8) & 0x0000FF00; + int B = (this.b) & 0x000000FF; + return Alpha | R | G | B; + } + + public String getColorAsHex() { + return String.format("#%06X", this.getColorAsInt()); + } + + public float getRed() { + return ((float) this.r) / 255.0f; + } + + public float getGreen() { + return ((float) this.g) / 255.0f; + } + + public float getBlue() { + return ((float) this.b) / 255.0f; + } + + public float getAlpha() { + return ((float) this.alpha) / 255.0f; + } + + public Color add(Color color) { + return new Color(this.r + color.r, this.g + color.g, this.b + color.b); + } + + public Color add(float r, float g, float b) { + return new Color((int) Math.min(255, this.r + r), (int) Math.min(255, this.g + g), + (int) Math.min(255, this.b + b)); + } + + public static String rgbToString(int r, int g, int b) { + String rs = Integer.toString((int) (r)); + String gs = Integer.toString((int) (g)); + String bs = Integer.toString((int) (b)); + return rs + gs + bs; + } + + public static int rgbToInt(int r, int g, int b) { + String rs = Integer.toString((int) (r)); + String gs = Integer.toString((int) (g)); + String bs = Integer.toString((int) (b)); + return Integer.parseInt(rs + gs + bs); + } + + public static int convertRGBToHex(int r, int g, int b) { + String strr = StringUtils.leftPad(Integer.toHexString(r), 2, '0'); + String strg = StringUtils.leftPad(Integer.toHexString(g), 2, '0'); + String strb = StringUtils.leftPad(Integer.toHexString(b), 2, '0'); + String string = strr + strg + strb; + return Integer.parseInt(string, 16); + } + + public static Color convertHextoRGB(String hexColor) { + hexColor = hexColor.replace("#", ""); + if (hexColor.length() == 6) { + int r = Integer.valueOf(hexColor.substring(0, 2), 16); + int g = Integer.valueOf(hexColor.substring(2, 4), 16); + int b = Integer.valueOf(hexColor.substring(4, 6), 16); + return new Color(r, g, b); + } else if (hexColor.length() == 8) { + int alpha = Integer.valueOf(hexColor.substring(0, 2), 16); + int r = Integer.valueOf(hexColor.substring(2, 4), 16); + int g = Integer.valueOf(hexColor.substring(4, 6), 16); + int b = Integer.valueOf(hexColor.substring(6, 8), 16); + return new Color(r, g, b, alpha); + } else { + throw new IllegalArgumentException("Invalid hex color format. Expected 6 or 8 characters."); + } + } + + public static Color hsv2rgb(float hue, float saturation, float luminance) { + float h = (hue / 60); + float chroma = luminance * saturation; + float x = chroma * (1 - Math.abs((h % 2) - 1)); + + Vector3f rgbVec; + if (h >= 0 && h <= 1) { + rgbVec = new Vector3f(chroma, x, 0); + } else if (h >= 1 && h <= 2) { + rgbVec = new Vector3f(x, chroma, 0); + } else if (h >= 2 && h <= 3) { + rgbVec = new Vector3f(0, chroma, x); + } else if (h >= 3 && h <= 4) { + rgbVec = new Vector3f(0, x, chroma); + } else if (h >= 4 && h <= 5) { + rgbVec = new Vector3f(x, 0, chroma); + } else if (h >= 5 && h <= 6) { + rgbVec = new Vector3f(chroma, 0, x); + } else { + rgbVec = null; + } + + if (rgbVec != null) { + float m = luminance - chroma; + return new Color((int) (255.0f * (rgbVec.x + m)), (int) (255.0f * (rgbVec.y + m)), + (int) (255.0f * (rgbVec.z + m))); + } + return null; + } +} diff --git a/src/main/java/online/bobtony/gui/Rectangle.java b/src/main/java/online/bobtony/gui/Rectangle.java new file mode 100644 index 0000000..a73036a --- /dev/null +++ b/src/main/java/online/bobtony/gui/Rectangle.java @@ -0,0 +1,102 @@ +package online.bobtony.gui; + +import java.util.Objects; + +import org.jetbrains.annotations.Nullable; + +public class Rectangle { + public static final Rectangle INFINITE = new Rectangle(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, + Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY); + + private Float x = null; + private Float y = null; + private Float width = null; + private Float height = null; + + public Rectangle() { + } + + public Rectangle(Float x, Float y, Float width, Float height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public Rectangle(Rectangle rect) { + this.x = rect.x; + this.y = rect.y; + this.width = rect.width; + this.height = rect.height; + } + + @Nullable + public Float getX() { + return this.x; + } + + @Nullable + public Float getY() { + return this.y; + } + + @Nullable + public Float getWidth() { + return this.width; + } + + @Nullable + public Float getHeight() { + return this.height; + } + + @Override + public boolean equals(Object other) { + if (this == other) + return true; + if (other == null || getClass() != other.getClass()) + return false; + + Rectangle otherRect = (Rectangle) other; + + if (!Objects.equals(x, otherRect.x)) + return false; + if (!Objects.equals(y, otherRect.y)) + return false; + if (!Objects.equals(width, otherRect.width)) + return false; + return Objects.equals(height, otherRect.height); + } + + public boolean intersects(Rectangle rectangle) { + return (Math.abs(x - rectangle.x) * 2 < (width + rectangle.width)) + && (Math.abs(y - rectangle.y) * 2 < (height + rectangle.height)); + } + + public boolean intersects(float x, float y) { + float x2 = this.x + width; + float y2 = this.y + height; + + return (x >= this.x && x <= x2 && y >= this.y && y <= y2); + } + + public void setX(Float x) { + this.x = x; + } + + public void setY(Float y) { + this.y = y; + } + + public void setWidth(Float width) { + this.width = width; + } + + public void setHeight(Float height) { + this.height = height; + } + + public boolean isDrawable() { + return !(x == null || y == null || width == null || height == null); + } +} \ No newline at end of file diff --git a/src/main/java/online/bobtony/gui/render/Render2D.java b/src/main/java/online/bobtony/gui/render/Render2D.java new file mode 100644 index 0000000..62a5618 --- /dev/null +++ b/src/main/java/online/bobtony/gui/render/Render2D.java @@ -0,0 +1,572 @@ +package online.bobtony.gui.render; + +import com.mojang.blaze3d.systems.RenderSystem; +import online.bobtony.gui.Color; +import online.bobtony.gui.Rectangle; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gl.ShaderProgramKeys; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.render.*; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RotationAxis; +import net.minecraft.util.math.Vec3d; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.opengl.GL11; + +public class Render2D { + public static Vec3d center; + + public static MinecraftClient mc = MinecraftClient.getInstance(); + + public static void updateScreenCenter() { + Vector3f pos = new Vector3f(0, 0, 1); + + if (mc.options.getBobView().getValue()) + { + MatrixStack bobViewMatrices = new MatrixStack(); + + bobView(bobViewMatrices); + pos.mulPosition(bobViewMatrices.peek().getPositionMatrix().invert()); + } + + center = new Vec3d(pos.x, -pos.y, pos.z) + .rotateX(-(float) Math.toRadians(mc.gameRenderer.getCamera().getPitch())) + .rotateY(-(float) Math.toRadians(mc.gameRenderer.getCamera().getYaw())) + .add(mc.gameRenderer.getCamera().getPos()); + } + + private static void bobView(MatrixStack matrices) { + Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity(); + + if (cameraEntity instanceof AbstractClientPlayerEntity abstractClientPlayerEntity) + { + float tickDelta = mc.getRenderTickCounter().getTickDelta(true); + + float var7 = abstractClientPlayerEntity.distanceMoved - abstractClientPlayerEntity.lastDistanceMoved; + float g = -(abstractClientPlayerEntity.distanceMoved + var7 * tickDelta); + float h = MathHelper.lerp(tickDelta, abstractClientPlayerEntity.prevStrideDistance, abstractClientPlayerEntity.strideDistance); + + matrices.translate(MathHelper.sin(g * (float) Math.PI) * h * 0.5F, -Math.abs(MathHelper.cos(g * (float) Math.PI) * h), 0.0F); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(MathHelper.sin(g * (float) Math.PI) * h * 3f)); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(Math.abs(MathHelper.cos(g * (float) Math.PI - 0.2f) * h) * 5f)); + } + } + + public static void drawTexturedQuad(Matrix4f matrix4f, Identifier texture, Rectangle size, Color color) { + drawTexturedQuad(matrix4f, texture, size.getX(), size.getY(), size.getWidth(), size.getHeight(), color); + } + + public static void drawTexturedQuad(Matrix4f matrix4f, Identifier texture, float x1, float y1, float width, float height, Color color) { + int colorInt = color.getColorAsInt(); + + float x2 = x1 + width; + float y2 = y1 + height; + + RenderSystem.setShaderTexture(0, texture); + RenderSystem.setShader(ShaderProgramKeys.POSITION_TEX_COLOR); + RenderSystem.enableBlend(); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, + VertexFormats.POSITION_TEXTURE_COLOR); + bufferBuilder.vertex(matrix4f, x1, y1, 0).color(colorInt).texture(0, 0); + bufferBuilder.vertex(matrix4f, x1, y2, 0).color(colorInt).texture(0, 1); + bufferBuilder.vertex(matrix4f, x2, y2, 0).color(colorInt).texture(1, 1); + bufferBuilder.vertex(matrix4f, x2, y1, 0).color(colorInt).texture(1, 0); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + RenderSystem.disableBlend(); + } + + public static void drawBox(Matrix4f matrix4f, Rectangle size, Color color) { + drawBox(matrix4f, size.getX(), size.getY(), size.getWidth(), size.getHeight(), color); + } + + public static void drawBox(Matrix4f matrix4f, float x, float y, float width, float height, Color color) { + int colorInt = color.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + bufferBuilder.vertex(matrix4f, x, y, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width, y, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x, y + height, 0).color(colorInt); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawRoundedBox(Matrix4f matrix4f, Rectangle size, float radius, Color color) { + drawRoundedBox(matrix4f, size.getX(), size.getY(), size.getWidth(), size.getHeight(), radius, color); + } + + public static void drawRoundedBox(Matrix4f matrix4f, float x, float y, float width, float height, float radius, Color color) { + int colorInt = color.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); + buildFilledArc(bufferBuilder, matrix4f, x + radius, y + radius, radius, 180.0f, 90.0f, color); + buildFilledArc(bufferBuilder, matrix4f, x + width - radius, y + radius, radius, 270.0f, 90.0f, color); + buildFilledArc(bufferBuilder, matrix4f, x + width - radius, y + height - radius, radius, 0.0f, 90.0f, color); + buildFilledArc(bufferBuilder, matrix4f, x + radius, y + height - radius, radius, 90.0f, 90.0f, color); + + bufferBuilder.vertex(matrix4f, x + radius, y, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + radius, 0).color(colorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + radius, 0).color(colorInt); + + bufferBuilder.vertex(matrix4f, x + width - radius, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height - radius, 0).color(colorInt); + + bufferBuilder.vertex(matrix4f, x + width, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height - radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height - radius, 0).color(colorInt); + + bufferBuilder.vertex(matrix4f, x + width - radius, y + height - radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(colorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height, 0).color(colorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x, y + height - radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x, y + radius, 0).color(colorInt); + + bufferBuilder.vertex(matrix4f, x, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(colorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(colorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height - radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + radius, 0).color(colorInt); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawCircle(Matrix4f matrix4f, float x, float y, float radius, Color color) { + int colorInt = color.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLES, VertexFormats.POSITION_COLOR); + double roundedInterval = (360.0f / 30.0f); + + for (int i = 0; i < 30; i++) { + double angle = Math.toRadians(0 + (i * roundedInterval)); + double angle2 = Math.toRadians(0 + ((i + 1) * roundedInterval)); + float radiusX1 = (float) (Math.cos(angle) * radius); + float radiusY1 = (float) Math.sin(angle) * radius; + float radiusX2 = (float) Math.cos(angle2) * radius; + float radiusY2 = (float) Math.sin(angle2) * radius; + + bufferBuilder.vertex(matrix4f, x, y, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radiusX1, y + radiusY1, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radiusX2, y + radiusY2, 0).color(colorInt); + } + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawTranslucentBlurredRoundedBox(Matrix4f matrix4f, float x, float y, float width, float height, float radius, Color color) { + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + for (int i = 0; i < 5; i++) { + float r = color.getRed(); + float g = color.getGreen(); + float b = color.getBlue(); + float alpha = color.getAlpha() * (1.0f / (i + 1)); + + Color newColor = new Color(r, g, b, alpha); + drawRoundedBox(matrix4f, x - i, y - i, width + 2 * i, height + 2 * i, radius + i, newColor); + } + + drawRoundedBox(matrix4f, x, y, width, height, radius, color); + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawOutlinedBox(Matrix4f matrix4f, Rectangle size, Color outlineColor, Color backgroundColor) { + drawOutlinedBox(matrix4f, size.getX(), size.getY(), size.getWidth(), size.getHeight(), outlineColor, + backgroundColor); + } + + public static void drawOutlinedBox(Matrix4f matrix4f, float x, float y, float width, float height, Color outlineColor, Color backgroundColor) { + int backgroundColorInt = backgroundColor.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + bufferBuilder.vertex(matrix4f, x, y, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width, y, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x, y + height, 0).color(backgroundColorInt); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + int outlineColorInt = outlineColor.getColorAsInt(); + + bufferBuilder = tessellator.begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP, VertexFormats.POSITION_COLOR); + bufferBuilder.vertex(matrix4f, x, y, 0).color(outlineColorInt); + bufferBuilder.vertex(matrix4f, x + width, y, 0).color(outlineColorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0).color(outlineColorInt); + bufferBuilder.vertex(matrix4f, x, y + height, 0).color(outlineColorInt); + bufferBuilder.vertex(matrix4f, x, y, 0).color(outlineColorInt); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawBoxOutline(Matrix4f matrix4f, Rectangle size, Color color) { + drawBoxOutline(matrix4f, size.getX(), size.getY(), size.getWidth(), size.getHeight(), color); + } + + public static void drawBoxOutline(Matrix4f matrix4f, float x, float y, float width, float height, Color color) { + int colorInt = color.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP, + VertexFormats.POSITION_COLOR); + bufferBuilder.vertex(matrix4f, x, y, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width, y, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x, y + height, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x, y, 0).color(colorInt); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawRoundedBoxOutline(Matrix4f matrix4f, Rectangle size, float radius, Color color) { + drawRoundedBoxOutline(matrix4f, size.getX(), size.getY(), size.getWidth(), size.getHeight(), radius, color); + } + + public static void drawOutlinedRoundedBox(Matrix4f matrix4f, float x, float y, float width, float height, float radius, Color outlineColor, Color backgroundColor) { + int backgroundColorInt = backgroundColor.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLES, VertexFormats.POSITION_COLOR); + buildFilledArc(bufferBuilder, matrix4f, x + radius, y + radius, radius, 180.0f, 90.0f, backgroundColor); + buildFilledArc(bufferBuilder, matrix4f, x + width - radius, y + radius, radius, 270.0f, 90.0f, backgroundColor); + buildFilledArc(bufferBuilder, matrix4f, x + width - radius, y + height - radius, radius, 0.0f, 90.0f, + backgroundColor); + buildFilledArc(bufferBuilder, matrix4f, x + radius, y + height - radius, radius, 90.0f, 90.0f, backgroundColor); + + bufferBuilder.vertex(matrix4f, x + radius, y, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + radius, 0).color(backgroundColorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + radius, 0).color(backgroundColorInt); + + bufferBuilder.vertex(matrix4f, x + width - radius, y + radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width, y + radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height - radius, 0).color(backgroundColorInt); + + bufferBuilder.vertex(matrix4f, x + width, y + radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height - radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height - radius, 0).color(backgroundColorInt); + + bufferBuilder.vertex(matrix4f, x + width - radius, y + height - radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(backgroundColorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height, 0).color(backgroundColorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x, y + height - radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x, y + radius, 0).color(backgroundColorInt); + + bufferBuilder.vertex(matrix4f, x, y + radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(backgroundColorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(backgroundColorInt); + + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height - radius, 0).color(backgroundColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + radius, 0).color(backgroundColorInt); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + int outlineColorInt = outlineColor.getColorAsInt(); + + bufferBuilder = tessellator.begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP, VertexFormats.POSITION_COLOR); + buildArc(bufferBuilder, matrix4f, x + radius, y + radius, radius, 180.0f, 90.0f, outlineColor); + bufferBuilder.vertex(matrix4f, x + radius, y, 0).color(outlineColorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y, 0).color(outlineColorInt); + + buildArc(bufferBuilder, matrix4f, x + width - radius, y + radius, radius, 270.0f, 90.0f, outlineColor); + bufferBuilder.vertex(matrix4f, x + width, y + radius, 0).color(outlineColorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height - radius, 0).color(outlineColorInt); + + buildArc(bufferBuilder, matrix4f, x + width - radius, y + height - radius, radius, 0.0f, 90.0f, outlineColor); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height, 0).color(outlineColorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height, 0).color(outlineColorInt); + + buildArc(bufferBuilder, matrix4f, x + radius, y + height - radius, radius, 90.0f, 90.0f, outlineColor); + bufferBuilder.vertex(matrix4f, x, y + height - radius, 0).color(outlineColorInt); + bufferBuilder.vertex(matrix4f, x, y + radius, 0).color(outlineColorInt); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawRoundedBoxOutline(Matrix4f matrix4f, float x, float y, float width, float height, float radius, Color color) { + int colorInt = color.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP, VertexFormats.POSITION_COLOR); + buildArc(bufferBuilder, matrix4f, x + radius, y + radius, radius, 180.0f, 90.0f, color); + bufferBuilder.vertex(matrix4f, x + radius, y, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y, 0).color(colorInt); + + buildArc(bufferBuilder, matrix4f, x + width - radius, y + radius, radius, 270.0f, 90.0f, color); + bufferBuilder.vertex(matrix4f, x + width, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height - radius, 0).color(colorInt); + + buildArc(bufferBuilder, matrix4f, x + width - radius, y + height - radius, radius, 0.0f, 90.0f, color); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height, 0).color(colorInt); + + buildArc(bufferBuilder, matrix4f, x + radius, y + height - radius, radius, 90.0f, 90.0f, color); + bufferBuilder.vertex(matrix4f, x, y + height - radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x, y + radius, 0).color(colorInt); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawLine(Matrix4f matrix4f, float x1, float y1, float x2, float y2, Color color) { + int colorInt = color.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.DEBUG_LINES, + VertexFormats.POSITION_COLOR); + bufferBuilder.vertex(matrix4f, x1, y1, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x2, y2, 0).color(colorInt); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawHorizontalGradient(Matrix4f matrix4f, Rectangle size, Color startColor, Color endColor) { + drawHorizontalGradient(matrix4f, size.getX(), size.getY(), size.getWidth(), size.getHeight(), startColor, endColor); + } + + public static void drawHorizontalGradient(Matrix4f matrix4f, float x, float y, float width, float height, Color startColor, Color endColor) { + int startColorInt = startColor.getColorAsInt(); + int endColorInt = endColor.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + bufferBuilder.vertex(matrix4f, x, y, 0.0F).color(startColorInt); + bufferBuilder.vertex(matrix4f, x + width, y, 0.0F).color(endColorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0.0F).color(endColorInt); + bufferBuilder.vertex(matrix4f, x, y + height, 0.0F).color(startColorInt); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawVerticalGradient(Matrix4f matrix4f, Rectangle size, Color startColor, Color endColor) { + drawVerticalGradient(matrix4f, size.getX(), size.getY(), size.getWidth(), size.getHeight(), startColor, endColor); + } + + public static void drawVerticalGradient(Matrix4f matrix4f, float x, float y, float width, float height, Color startColor, Color endColor) { + int startColorInt = startColor.getColorAsInt(); + int endColorInt = endColor.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + bufferBuilder.vertex(matrix4f, x, y, 0.0F).color(startColorInt); + bufferBuilder.vertex(matrix4f, x + width, y, 0.0F).color(startColorInt); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0.0F).color(endColorInt); + bufferBuilder.vertex(matrix4f, x, y + height, 0.0F).color(endColorInt); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + public static void drawItem(DrawContext drawContext, ItemStack stack, float x, float y) { + drawContext.drawItem(stack, (int) x, (int) y); + } + + public static void drawString(DrawContext drawContext, String text, Vec3d pos, Color color) { + + } + + public static void drawStringWithScale(DrawContext drawContext, String text, float x, float y, Color color, float scale) { + MinecraftClient client = MinecraftClient.getInstance(); + MatrixStack matrixStack = drawContext.getMatrices(); + matrixStack.push(); + matrixStack.scale(scale, scale, 1.0f); + if (scale > 1.0f) { + matrixStack.translate(-x / scale, -y / scale, 0.0f); + } + else { + matrixStack.translate((x / scale) - x, (y * scale) - y, 0.0f); + } + drawContext.drawText(client.textRenderer, text, (int) x, (int) y, color.getColorAsInt(), false); + matrixStack.pop(); + } + + public static void buildFilledArc(BufferBuilder bufferBuilder, Matrix4f matrix, float x, float y, float radius, float startAngle, float sweepAngle, Color color) { + double roundedInterval = (sweepAngle / radius); + + int colorInt = color.getColorAsInt(); + + for (int i = 0; i < radius; i++) { + double angle = Math.toRadians(startAngle + (i * roundedInterval)); + double angle2 = Math.toRadians(startAngle + ((i + 1) * roundedInterval)); + float radiusX1 = (float) (Math.cos(angle) * radius); + float radiusY1 = (float) Math.sin(angle) * radius; + float radiusX2 = (float) Math.cos(angle2) * radius; + float radiusY2 = (float) Math.sin(angle2) * radius; + + bufferBuilder.vertex(matrix, x, y, 0).color(colorInt); + bufferBuilder.vertex(matrix, x + radiusX1, y + radiusY1, 0).color(colorInt); + bufferBuilder.vertex(matrix, x + radiusX2, y + radiusY2, 0).color(colorInt); + } + } + + public static void drawRoundedBox2(Matrix4f matrix4f, float x, float y, float width, float height, float radius, Color color) { + int colorInt = color.getColorAsInt(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); + + bufferBuilder.vertex(matrix4f, x + radius, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + radius, y + height - radius, 0).color(colorInt); + bufferBuilder.vertex(matrix4f, x + width - radius, y + height - radius, 0).color(colorInt); + + buildFilledArc(bufferBuilder, matrix4f, x + radius, y + radius, radius, 180.0f, 90.0f, color); + buildFilledArc(bufferBuilder, matrix4f, x + width - radius, y + radius, radius, 270.0f, 90.0f, color); + buildFilledArc(bufferBuilder, matrix4f, x + width - radius, y + height - radius, radius, 0.0f, 90.0f, color); + buildFilledArc(bufferBuilder, matrix4f, x + radius, y + height - radius, radius, 90.0f, 90.0f, color); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + private static void buildArc(BufferBuilder bufferBuilder, Matrix4f matrix, float x, float y, float radius, float startAngle, float sweepAngle, Color color) { + float roundedInterval = (sweepAngle / radius); + + int colorInt = color.getColorAsInt(); + for (int i = 0; i < radius; i++) { + double angle = Math.toRadians(startAngle + (i * roundedInterval)); + float radiusX1 = (float) (Math.cos(angle) * radius); + float radiusY1 = (float) Math.sin(angle) * radius; + + bufferBuilder.vertex(matrix, x + radiusX1, y + radiusY1, 0).color(colorInt); + } + } + + public static int getStringWidth(String text) { + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + return textRenderer.getWidth(text); + } +} \ No newline at end of file diff --git a/src/main/java/online/bobtony/gui/render/RoundedBoxRenderer.java b/src/main/java/online/bobtony/gui/render/RoundedBoxRenderer.java new file mode 100644 index 0000000..762cc94 --- /dev/null +++ b/src/main/java/online/bobtony/gui/render/RoundedBoxRenderer.java @@ -0,0 +1,61 @@ +package online.bobtony.gui.render; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gl.ShaderProgramKeys; +import net.minecraft.client.render.*; +import org.lwjgl.opengl.GL11; +import org.joml.Matrix4f; + +import java.awt.Color; + +public class RoundedBoxRenderer { + public static void drawRoundedBox(Matrix4f matrix4f, float x, float y, float width, float height, float radius, Color color) { + int colorInt = color.getRGB(); + + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + GL11.glEnable(GL11.GL_LINE_SMOOTH); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.LINES, VertexFormats.POSITION_COLOR); + + drawFilledArc(bufferBuilder, matrix4f, x + radius, y + radius, radius, 180.0f, 90.0f, colorInt); + drawFilledArc(bufferBuilder, matrix4f, x + width - radius, y + radius, radius, 270.0f, 90.0f, colorInt); + drawFilledArc(bufferBuilder, matrix4f, x + width - radius, y + height - radius, radius, 0.0f, 90.0f, colorInt); + drawFilledArc(bufferBuilder, matrix4f, x + radius, y + height - radius, radius, 90.0f, 90.0f, colorInt); + + drawRect(bufferBuilder, matrix4f, x + radius, y, width - 2 * radius, height, colorInt); + drawRect(bufferBuilder, matrix4f, x, y + radius, width, height - 2 * radius, colorInt); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + GL11.glDisable(GL11.GL_LINE_SMOOTH); + RenderSystem.disableBlend(); + RenderSystem.enableDepthTest(); + } + + private static void drawRect(BufferBuilder buffer, Matrix4f matrix, float x, float y, float width, float height, int color) { + buffer.vertex(matrix, x, y, 0).color(color); + buffer.vertex(matrix, x + width, y, 0).color(color); + buffer.vertex(matrix, x + width, y + height, 0).color(color); + buffer.vertex(matrix, x, y + height, 0).color(color); + } + + private static void drawFilledArc(BufferBuilder buffer, Matrix4f matrix, float cx, float cy, float radius, float startAngle, float arcAngle, int color) { + int segments = 20; + float angleStep = arcAngle / segments; + for (int i = 0; i < segments; i++) { + float theta1 = (float) Math.toRadians(startAngle + i * angleStep); + float theta2 = (float) Math.toRadians(startAngle + (i + 1) * angleStep); + + float x1 = cx + (float) Math.cos(theta1) * radius; + float y1 = cy + (float) Math.sin(theta1) * radius; + float x2 = cx + (float) Math.cos(theta2) * radius; + float y2 = cy + (float) Math.sin(theta2) * radius; + + buffer.vertex(matrix, cx, cy, 0).color(color); + buffer.vertex(matrix, x1, y1, 0).color(color); + buffer.vertex(matrix, x2, y2, 0).color(color); + } + } +} \ No newline at end of file diff --git a/src/main/java/online/bobtony/gui/widgets/RoundedButton.java b/src/main/java/online/bobtony/gui/widgets/RoundedButton.java new file mode 100644 index 0000000..c64e2cc --- /dev/null +++ b/src/main/java/online/bobtony/gui/widgets/RoundedButton.java @@ -0,0 +1,56 @@ +package online.bobtony.gui.widgets; + +import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.sound.SoundEvents; +import online.bobtony.gui.render.Render2D; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.widget.ClickableWidget; +import online.bobtony.gui.Color; +import net.minecraft.text.Text; +import org.joml.Matrix4f; + +public class RoundedButton extends ClickableWidget { + private final Runnable onClick; + private final Color color; + private final Color hoverColor; + private boolean isHovered = false; + + public RoundedButton(int x, int y, int width, int height, Text message, Color color, Runnable onClick) { + super(x, y, width, height, message); + this.color = color; + this.hoverColor = color.add(1.0F, 1.0F, 1.0F); + this.onClick = onClick; + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + isHovered = isMouseOver(mouseX, mouseY); + Matrix4f matrix4f = context.getMatrices().peek().getPositionMatrix(); + drawRoundedBox(matrix4f, getX(), getY(), getWidth(), getHeight(), 2, isHovered ? hoverColor : color); + + int textX = getX() + getWidth() / 2; + int textY = getY() + getHeight() / 2 - 4; + context.drawCenteredTextWithShadow(MinecraftClient.getInstance().textRenderer, getMessage(), textX, textY, 0xFFFFFF); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (isMouseOver(mouseX, mouseY) && button == 0) { + onClick.run(); + PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F); + return true; + } + return false; + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + + } + + public static void drawRoundedBox(Matrix4f matrix4f, float x, float y, float width, float height, float radius, Color color) { + Render2D.drawRoundedBoxOutline(matrix4f, x, y, width, height, radius, color); + } +} \ No newline at end of file diff --git a/src/main/java/online/bobtony/handlers/ChestESPHandler.java b/src/main/java/online/bobtony/handlers/ChestESPHandler.java new file mode 100644 index 0000000..e506cdb --- /dev/null +++ b/src/main/java/online/bobtony/handlers/ChestESPHandler.java @@ -0,0 +1,17 @@ +package online.bobtony.handlers; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.Text; +import online.bobtony.BobTony; + +public class ChestESPHandler { + public static void handleChestESP(){ + MinecraftClient client = MinecraftClient.getInstance(); + BobTony.chestesp = !BobTony.chestesp; + if (BobTony.chestesp){ + BobTony.sendMessage(client.player, "ChestESP: §aOn", false); + }else { + BobTony.sendMessage(client.player, "ChestESP: §cOff", false); + } + } +} diff --git a/src/main/java/online/bobtony/handlers/DoubleJumpHandler.java b/src/main/java/online/bobtony/handlers/DoubleJumpHandler.java new file mode 100644 index 0000000..b665f25 --- /dev/null +++ b/src/main/java/online/bobtony/handlers/DoubleJumpHandler.java @@ -0,0 +1,55 @@ +package online.bobtony.handlers; + +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.util.math.Vec3d; +import online.bobtony.BobTony; +import online.bobtony.enums.Modes; + +public class DoubleJumpHandler { + + public static void handleDoubleJump(ClientPlayerEntity player) { + boolean isJumping = player.input.playerInput.jump(); + + if (isJumping && !BobTony.wasJumping) { + long currentTime = System.currentTimeMillis(); + if (currentTime - BobTony.lastJumpTime < 300) { + if(BobTony.mode == Modes.FLY) { + toggleFlyMode(player); + }else { + boostPlayer(player); + } + } + BobTony.lastJumpTime = currentTime; + } + + BobTony.wasJumping = isJumping; + } + + private static void toggleFlyMode(ClientPlayerEntity player) { + boolean isFlying = !player.getAbilities().flying; + player.getAbilities().flying = isFlying; + player.getAbilities().setFlySpeed(BobTony.flyspeed); + + if (isFlying) { + BobTony.sendMessage(player, "Fly: §aEnabled", true); + } else { + BobTony.sendMessage(player, "Fly: §cDisabled", true); + } + + player.sendAbilitiesUpdate(); + } + + private static void boostPlayer(ClientPlayerEntity apfel) { + double pitch = apfel.getPitch(); + Vec3d velocity; + + if (pitch > 70) { + velocity = new Vec3d(0.0, 1.0, 0.0).multiply(BobTony.strength); + } else { + velocity = apfel.getRotationVector().multiply(BobTony.strength); + } + + apfel.addVelocity(velocity.x, velocity.y + 0.5, velocity.z); + apfel.velocityModified = true; + } +} diff --git a/src/main/java/online/bobtony/handlers/FlyHandler.java b/src/main/java/online/bobtony/handlers/FlyHandler.java new file mode 100644 index 0000000..9abb4ed --- /dev/null +++ b/src/main/java/online/bobtony/handlers/FlyHandler.java @@ -0,0 +1,19 @@ +package online.bobtony.handlers; + +import net.minecraft.client.MinecraftClient; +import online.bobtony.BobTony; +import online.bobtony.enums.Modes; + +public class FlyHandler { + public static void handleFly(){ + MinecraftClient client = MinecraftClient.getInstance(); + + if (BobTony.mode != Modes.FLY){ + BobTony.mode = Modes.FLY; + BobTony.sendMessage(client.player, "Fly: §aOn", false); + }else { + BobTony.mode = Modes.NONE; + BobTony.sendMessage(client.player, "Fly: §cOff", false); + } + } +} diff --git a/src/main/java/online/bobtony/handlers/FlySpeedCommandHandler.java b/src/main/java/online/bobtony/handlers/FlySpeedCommandHandler.java new file mode 100644 index 0000000..1083353 --- /dev/null +++ b/src/main/java/online/bobtony/handlers/FlySpeedCommandHandler.java @@ -0,0 +1,30 @@ +package online.bobtony.handlers; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import online.bobtony.BobTony; + +public class FlySpeedCommandHandler { + static float flyspeed = BobTony.flyspeed; + + public static void handelFlySpeedCommand(String message){ + MinecraftClient client = MinecraftClient.getInstance(); + String[] parts = message.split(" "); + if (parts.length == 2) { + try { + adjustFlySpeed(client.player, Float.parseFloat(parts[1])); + BobTony.sendMessage(client.player, "Flyspeed: §c" + flyspeed, false); + } catch (NumberFormatException e) { + BobTony.sendMessage(client.player, "§cKeine richtige Zahl!", false); + } + } else { + BobTony.sendMessage(client.player, "§cUsage: .strength ", false); + } + } + + private static void adjustFlySpeed(ClientPlayerEntity player, float amount) { + flyspeed = amount; + player.getAbilities().setFlySpeed(flyspeed); + player.sendAbilitiesUpdate(); + } +} diff --git a/src/main/java/online/bobtony/handlers/ModeSwitchHandler.java b/src/main/java/online/bobtony/handlers/ModeSwitchHandler.java new file mode 100644 index 0000000..286ede5 --- /dev/null +++ b/src/main/java/online/bobtony/handlers/ModeSwitchHandler.java @@ -0,0 +1,24 @@ +package online.bobtony.handlers; + +import net.minecraft.client.network.ClientPlayerEntity; +import online.bobtony.BobTony; +import online.bobtony.enums.Modes; + +public class ModeSwitchHandler { + public static void handleModeSwitch(ClientPlayerEntity player) { + long currentTime = System.currentTimeMillis(); + if (BobTony.toggleModeKey.isPressed() && currentTime - BobTony.lastModeSwitchTime > BobTony.MODE_SWITCH_COOLDOWN) { + if (BobTony.mode == Modes.FLY){ + BobTony.mode = Modes.BOOST; + BobTony.sendMessage(player, " Fly: §cOff", false); + BobTony.sendMessage(player, " Boost: §aOn", false); + }else { + BobTony.mode = Modes.FLY; + BobTony.sendMessage(player, " Fly: §cOn", false); + BobTony.sendMessage(player, " Boost: §aOff", false); + } + + BobTony.lastModeSwitchTime = currentTime; + } + } +} diff --git a/src/main/java/online/bobtony/handlers/NoFallCommandHandler.java b/src/main/java/online/bobtony/handlers/NoFallCommandHandler.java new file mode 100644 index 0000000..6d5a451 --- /dev/null +++ b/src/main/java/online/bobtony/handlers/NoFallCommandHandler.java @@ -0,0 +1,17 @@ +package online.bobtony.handlers; + +import net.minecraft.client.MinecraftClient; +import online.bobtony.BobTony; + +public class NoFallCommandHandler { + + public static void handelNoFallCommand(){ + MinecraftClient client = MinecraftClient.getInstance(); + BobTony.nofall = !BobTony.nofall; + if (BobTony.nofall){ + BobTony.sendMessage(client.player, "NoFall: §aOn", false); + }else { + BobTony.sendMessage(client.player, "NoFall: §cOff", false); + } + } +} diff --git a/src/main/java/online/bobtony/handlers/NukeCommandHandler.java b/src/main/java/online/bobtony/handlers/NukeCommandHandler.java new file mode 100644 index 0000000..11cfc71 --- /dev/null +++ b/src/main/java/online/bobtony/handlers/NukeCommandHandler.java @@ -0,0 +1,19 @@ +package online.bobtony.handlers; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; +import net.minecraft.server.MinecraftServer; + +public class NukeCommandHandler { + public static void handleNukeCommand() { + MinecraftClient client = MinecraftClient.getInstance(); + MinecraftServer server = client.getServer(); + + if (server != null) { + server.getOverworld().getPlayers().forEach(player -> { + PlayerInteractEntityC2SPacket packet = PlayerInteractEntityC2SPacket.attack(player, client.player.isSneaking()); + client.getNetworkHandler().sendPacket(packet); + }); + } + } +} diff --git a/src/main/java/online/bobtony/handlers/SimulateMovementHandler.java b/src/main/java/online/bobtony/handlers/SimulateMovementHandler.java new file mode 100644 index 0000000..1344f1f --- /dev/null +++ b/src/main/java/online/bobtony/handlers/SimulateMovementHandler.java @@ -0,0 +1,42 @@ +package online.bobtony.handlers; + +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import online.bobtony.BobTony; + +public class SimulateMovementHandler { + + public static void simulateMovement(ClientPlayerEntity player) { + new Thread(() -> { + try { + boolean wasSneaking = player.input.playerInput.sneak(); + boolean wasTouchingCeiling = false; + while (player.getAbilities().flying) { + boolean isSneaking = player.input.playerInput.sneak(); + + if (!isSneaking) { + long currentTime = System.currentTimeMillis(); + if (currentTime - BobTony.lastUpdateTime > 50) { + player.networkHandler.sendPacket( + new PlayerMoveC2SPacket.PositionAndOnGround( + player.getX(), player.getY() + 0.05, player.getZ(), true, false + ) + ); + player.networkHandler.sendPacket( + new PlayerMoveC2SPacket.PositionAndOnGround( + player.getX(), player.getY(), player.getZ(), true, false + ) + ); + BobTony.lastUpdateTime = currentTime; + } + } + + wasSneaking = isSneaking; + + Thread.sleep(50); + } + } catch (InterruptedException ignored) { + } + }).start(); + } +} diff --git a/src/main/java/online/bobtony/handlers/SpeedCommandHandler.java b/src/main/java/online/bobtony/handlers/SpeedCommandHandler.java new file mode 100644 index 0000000..c5e9330 --- /dev/null +++ b/src/main/java/online/bobtony/handlers/SpeedCommandHandler.java @@ -0,0 +1,24 @@ +package online.bobtony.handlers; + +import net.minecraft.client.MinecraftClient; +import online.bobtony.BobTony; + +public class SpeedCommandHandler { + + public static void handleSpeedCommand(String message){ + MinecraftClient client = MinecraftClient.getInstance(); + + String[] parts = message.split(" "); + if (parts.length == 2) { + try { + BobTony.speed = Float.parseFloat(parts[1]); + client.player.setMovementSpeed(0.3f); + BobTony.sendMessage(client.player, "Speed: §c" + client.player.getMovementSpeed(), false); + } catch (NumberFormatException e) { + BobTony.sendMessage(client.player, "§cKeine richtige Zahl!", false); + } + } else { + BobTony.sendMessage(client.player, "§cUsage: .speed ", false); + } + } +} diff --git a/src/main/java/online/bobtony/handlers/StrengthCommandHandler.java b/src/main/java/online/bobtony/handlers/StrengthCommandHandler.java new file mode 100644 index 0000000..39cdea7 --- /dev/null +++ b/src/main/java/online/bobtony/handlers/StrengthCommandHandler.java @@ -0,0 +1,21 @@ +package online.bobtony.handlers; + +import net.minecraft.client.MinecraftClient; +import online.bobtony.BobTony; + +public class StrengthCommandHandler { + public static void handleStrengthCommand(String message) { + MinecraftClient client = MinecraftClient.getInstance(); + String[] parts = message.split(" "); + if (parts.length == 2) { + try { + BobTony.strength = Float.parseFloat(parts[1]); + BobTony.sendMessage(client.player, "Boost Strength: §c" + BobTony.strength, false); + } catch (NumberFormatException e) { + BobTony.sendMessage(client.player, "§cKeine richtige Zahl!", false); + } + } else { + BobTony.sendMessage(client.player, "§cUsage: .strength ", false); + } + } +} diff --git a/src/main/java/online/bobtony/handlers/TrackerHandler.java b/src/main/java/online/bobtony/handlers/TrackerHandler.java new file mode 100644 index 0000000..edafcd4 --- /dev/null +++ b/src/main/java/online/bobtony/handlers/TrackerHandler.java @@ -0,0 +1,23 @@ +package online.bobtony.handlers; + +import net.minecraft.client.MinecraftClient; +import online.bobtony.BobTony; + +public class TrackerHandler { + + public static void handleTracker(String message){ + MinecraftClient client = MinecraftClient.getInstance(); + + String[] parts = message.split(" "); + if (parts.length == 3) { + if (parts[1].equals("add")){ + BobTony.trackerList.add(parts[2]); + BobTony.sendMessage(client.player, "§aAdded " + parts[2] + " to Trackerlist: " + BobTony.trackerList, false); + }else if (parts[1].equals("remove")){ + BobTony.trackerList.remove(parts[2]); + } + } else { + BobTony.sendMessage(client.player, "§cUsage: .tracker ", false); + } + } +} diff --git a/src/main/java/online/bobtony/handlers/ZoomHandler.java b/src/main/java/online/bobtony/handlers/ZoomHandler.java new file mode 100644 index 0000000..801cb65 --- /dev/null +++ b/src/main/java/online/bobtony/handlers/ZoomHandler.java @@ -0,0 +1,49 @@ +package online.bobtony.handlers; + +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import org.lwjgl.glfw.GLFW; + +public class ZoomHandler { + private static boolean isZooming = false; + private static final int DEFAULT_FOV = MinecraftClient.getInstance().options.getFov().getValue(); + private static final int ZOOMED_FOV = 30; + private static final int ZOOM_SPEED = 2; + + private static KeyBinding zoomKey; + + public static void initialize() { + zoomKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( + "bobtony.zoom", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_C, + "BobTony" + )); + + ClientTickEvents.END_CLIENT_TICK.register(client -> { + boolean shouldZoom = zoomKey.isPressed(); + + if (shouldZoom != isZooming) { + isZooming = shouldZoom; + } + + int currentFov = client.options.getFov().getValue(); + int targetFov = isZooming ? ZOOMED_FOV : DEFAULT_FOV; + + if (currentFov != targetFov) { + int newFov = currentFov; + + if (isZooming) { + newFov = Math.max(targetFov, currentFov - ZOOM_SPEED); + } else { + newFov = Math.min(targetFov, currentFov + ZOOM_SPEED); + } + + client.options.getFov().setValue(newFov); + } + }); + } +} diff --git a/src/main/java/online/bobtony/mixin/AbstractClientPlayerEntityMixin.java b/src/main/java/online/bobtony/mixin/AbstractClientPlayerEntityMixin.java new file mode 100644 index 0000000..b4aeb15 --- /dev/null +++ b/src/main/java/online/bobtony/mixin/AbstractClientPlayerEntityMixin.java @@ -0,0 +1,31 @@ +package online.bobtony.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import online.bobtony.utils.CapeHandler; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.client.util.DefaultSkinHelper; +import net.minecraft.client.util.SkinTextures; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(AbstractClientPlayerEntity.class) +public class AbstractClientPlayerEntityMixin { + + @Shadow + private PlayerListEntry playerListEntry; + + @ModifyReturnValue(method = "getSkinTextures", at = @At("RETURN")) + public SkinTextures handelCapes(SkinTextures original){ + + if (playerListEntry == null) { + DefaultSkinHelper.getSkinTextures(((AbstractClientPlayerEntity) (Object) this).getUuid()); + }else { + return CapeHandler.getCapes(original, ((AbstractClientPlayerEntity) (Object) this)); + } + + return original; + } + +} diff --git a/src/main/java/online/bobtony/mixin/ClientPlayerEntityMixin.java b/src/main/java/online/bobtony/mixin/ClientPlayerEntityMixin.java new file mode 100644 index 0000000..687eb33 --- /dev/null +++ b/src/main/java/online/bobtony/mixin/ClientPlayerEntityMixin.java @@ -0,0 +1,18 @@ +package online.bobtony.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ClientPlayerEntity.class) +public class ClientPlayerEntityMixin { + + @Inject(method = "isSneaking", at = @At("HEAD"), cancellable = true) + private void onIsSneaking(CallbackInfoReturnable info) { + if (MinecraftClient.getInstance().player.getAbilities().flying) + info.setReturnValue(false); + } +} diff --git a/src/main/java/online/bobtony/mixin/EntityRendererMixin.java b/src/main/java/online/bobtony/mixin/EntityRendererMixin.java new file mode 100644 index 0000000..87b2a10 --- /dev/null +++ b/src/main/java/online/bobtony/mixin/EntityRendererMixin.java @@ -0,0 +1,29 @@ +package online.bobtony.mixin; + +import net.minecraft.client.render.entity.EntityRenderer; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArgs; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +@Mixin(EntityRenderer.class) +public class EntityRendererMixin { + + private Identifier font = Identifier.of("bobtony", "iconfont"); + + @ModifyArgs( + method = "renderLabelIfPresent", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/font/TextRenderer;draw(Lnet/minecraft/text/Text;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/render/VertexConsumerProvider;Lnet/minecraft/client/font/TextRenderer$TextLayerType;II)I" + ) + ) + private void modifyNameTag(Args args) { + Text originalText = args.get(0); + Text newText = Text.empty().append(Text.literal("").setStyle(Style.EMPTY.withFont(font))).append(" ").append(originalText); + args.set(0, newText); + } +} diff --git a/src/main/java/online/bobtony/mixin/GameRendererMixin.java b/src/main/java/online/bobtony/mixin/GameRendererMixin.java new file mode 100644 index 0000000..42997f8 --- /dev/null +++ b/src/main/java/online/bobtony/mixin/GameRendererMixin.java @@ -0,0 +1,31 @@ +package online.bobtony.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.blaze3d.systems.RenderSystem; +import online.bobtony.utils.render.WorldToScreen; +import net.minecraft.client.render.*; +import net.minecraft.client.util.ObjectAllocator; +import org.joml.Matrix4f; +import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(GameRenderer.class) +public abstract class GameRendererMixin { + + @WrapOperation(method = "renderWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;render(Lnet/minecraft/client/util/ObjectAllocator;Lnet/minecraft/client/render/RenderTickCounter;ZLnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/GameRenderer;Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V")) + void renderer_postWorldRender(WorldRenderer instance, ObjectAllocator allocator, RenderTickCounter tickCounter, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, Matrix4f positionMatrix, Matrix4f projectionMatrix, Operation original) { + original.call(instance, allocator, tickCounter, renderBlockOutline, camera, gameRenderer, positionMatrix, projectionMatrix); + + + WorldToScreen.lastProjMat.set(RenderSystem.getProjectionMatrix()); + WorldToScreen.lastModMat.set(RenderSystem.getModelViewMatrix()); + WorldToScreen.lastWorldSpaceMatrix.set(positionMatrix); + GL11.glGetIntegerv(GL11.GL_VIEWPORT, WorldToScreen.lastViewport); + + RenderSystem.depthMask(true); + RenderSystem.disableBlend(); + RenderSystem.setShaderFog(Fog.DUMMY); + } +} \ No newline at end of file diff --git a/src/main/java/online/bobtony/mixin/PlayerListEntryMixin.java b/src/main/java/online/bobtony/mixin/PlayerListEntryMixin.java new file mode 100644 index 0000000..8716293 --- /dev/null +++ b/src/main/java/online/bobtony/mixin/PlayerListEntryMixin.java @@ -0,0 +1,11 @@ +package online.bobtony.mixin; + +import net.minecraft.client.network.PlayerListEntry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(PlayerListEntry.class) +public interface PlayerListEntryMixin { + @Accessor("latency") + int getLatency(); +} diff --git a/src/main/java/online/bobtony/mixin/ServerPlayNetworkHanderMixin.java b/src/main/java/online/bobtony/mixin/ServerPlayNetworkHanderMixin.java new file mode 100644 index 0000000..9b29e8d --- /dev/null +++ b/src/main/java/online/bobtony/mixin/ServerPlayNetworkHanderMixin.java @@ -0,0 +1,12 @@ +package online.bobtony.mixin; + +import net.minecraft.server.network.ServerPlayNetworkHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ServerPlayNetworkHandler.class) +public class ServerPlayNetworkHanderMixin { + + private static final Logger LOGGER = LoggerFactory.getLogger("PacketLogger"); +} diff --git a/src/main/java/online/bobtony/mixin/TitleScreenMixin.java b/src/main/java/online/bobtony/mixin/TitleScreenMixin.java new file mode 100644 index 0000000..21451e8 --- /dev/null +++ b/src/main/java/online/bobtony/mixin/TitleScreenMixin.java @@ -0,0 +1,62 @@ +package online.bobtony.mixin; + +import online.bobtony.gui.Color; +import online.bobtony.gui.widgets.RoundedButton; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; +import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen; +import net.minecraft.client.gui.screen.option.OptionsScreen; +import net.minecraft.client.gui.screen.world.SelectWorldScreen; +import net.minecraft.text.Text; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(TitleScreen.class) +public abstract class TitleScreenMixin extends Screen { + + public TitleScreenMixin(Text title) { + super(title); + } + + @Inject(method = "init", at = @At("TAIL")) + private void addButtons(CallbackInfo ci) { + + int l = this.height / 4 + 48; + RoundedButton singleplayer = new RoundedButton(this.width / 2 - 100, l, 200, 20, Text.literal("Singleplayer"), new Color(255, 255, 255), () -> { + this.client.setScreen(new SelectWorldScreen(this)); + }); + + RoundedButton multiplayer = new RoundedButton(this.width / 2 - 100, l + 24, 200, 20, Text.literal("Multiplayer"), new Color(255, 255, 255), () -> { + Screen screen = this.client.options.skipMultiplayerWarning ? new MultiplayerScreen(this) : new MultiplayerWarningScreen(this); + this.client.setScreen(screen); + }); + + RoundedButton options = new RoundedButton( + this.width / 2 - 100, l + 48, 100, 20, + Text.literal("Options"), + new Color(255, 255, 255), + () -> this.client.setScreen(new OptionsScreen(this, this.client.options)) + ); + + RoundedButton quit = new RoundedButton( + this.width / 2, l + 48, 100, 20, + Text.literal("Quit Game"), + new Color(255, 255, 255), + () -> this.client.scheduleStop() + ); + + + clearChildren(); + blur(); + + this.addDrawableChild(singleplayer); + this.addDrawableChild(multiplayer); + this.addDrawableChild(options); + this.addDrawableChild(quit); + + } +} \ No newline at end of file diff --git a/src/main/java/online/bobtony/utils/CapeHandler.java b/src/main/java/online/bobtony/utils/CapeHandler.java new file mode 100644 index 0000000..7de7268 --- /dev/null +++ b/src/main/java/online/bobtony/utils/CapeHandler.java @@ -0,0 +1,28 @@ +package online.bobtony.utils; + +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.util.SkinTextures; +import net.minecraft.util.Identifier; + +public class CapeHandler { + + public static SkinTextures bobTexture; + public static Identifier capeTexture; + + public static SkinTextures getCapes(SkinTextures original, AbstractClientPlayerEntity player){ + + capeTexture = Identifier.of("bobtony", "textures/capes/cape.png"); + + bobTexture = new SkinTextures( + original.texture(), + original.textureUrl(), + capeTexture, + capeTexture, + original.model(), + original.secure() + ); + + return bobTexture; + } + +} diff --git a/src/main/java/online/bobtony/utils/Manager.java b/src/main/java/online/bobtony/utils/Manager.java new file mode 100644 index 0000000..2a1f78d --- /dev/null +++ b/src/main/java/online/bobtony/utils/Manager.java @@ -0,0 +1,42 @@ +package online.bobtony.utils; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class Manager { + + protected final ConcurrentHashMap entries = new ConcurrentHashMap<>(); + + public boolean register(@NotNull T key, @NotNull S value) { + return entries.putIfAbsent(key, value) == null; + } + + public boolean unregister(@NotNull T key) { + return entries.remove(key) != null; + } + + public @Nullable S get(@NotNull T key) { + return entries.get(key); + } + + public boolean contains(@NotNull T key) { + return entries.containsKey(key); + } + + public Collection values() { + return entries.values(); + } + + public Set> entries() { + return entries.entrySet(); + } + + public Set keys() { + return entries.keySet(); + } +} diff --git a/src/main/java/online/bobtony/utils/Registry.java b/src/main/java/online/bobtony/utils/Registry.java new file mode 100644 index 0000000..7ac22b0 --- /dev/null +++ b/src/main/java/online/bobtony/utils/Registry.java @@ -0,0 +1,30 @@ +package online.bobtony.utils; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.ConcurrentLinkedDeque; + +public abstract class Registry { + + private final ConcurrentLinkedDeque entries = new ConcurrentLinkedDeque<>(); + + + public boolean register(@NotNull T key) { + return entries.add(key); + } + + + public boolean unregister(@NotNull T key) { + return entries.remove(key); + } + + public boolean contains(@NotNull T key) { + return entries.contains(key); + } + public @Unmodifiable Collection entries() { + return Collections.unmodifiableCollection(this.entries); + } +} diff --git a/src/main/java/online/bobtony/utils/render/Render3D.java b/src/main/java/online/bobtony/utils/render/Render3D.java new file mode 100644 index 0000000..623acf4 --- /dev/null +++ b/src/main/java/online/bobtony/utils/render/Render3D.java @@ -0,0 +1,308 @@ +package online.bobtony.utils.render; + +import com.mojang.blaze3d.systems.RenderSystem; + +import online.bobtony.gui.Color; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.ShaderProgramKeys; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.*; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import org.joml.Matrix4f; +import org.joml.Quaternionf; + +public class Render3D { + public static void draw3DHitBox(MatrixStack matrices, Box box, Color color, float lineThickness) { + RenderSystem.setShaderColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.disableCull(); + RenderSystem.disableDepthTest(); + + RenderSystem.setShader(ShaderProgramKeys.RENDERTYPE_LINES); + RenderSystem.lineWidth(lineThickness); + + MatrixStack.Entry entry = matrices.peek(); + Matrix4f matrix4f = entry.getPositionMatrix(); + + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES); + + RenderSystem.setShaderColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + + buildLine3d(matrices, bufferBuilder, (float) box.minX, (float) box.minY, (float) box.minZ, (float) box.maxX, (float) box.minY, (float) box.minZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.maxX, (float) box.minY, (float) box.minZ, (float) box.maxX, (float) box.minY, (float) box.maxZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.maxX, (float) box.minY, (float) box.maxZ, (float) box.minX, (float) box.minY, (float) box.maxZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.minX, (float) box.minY, (float) box.maxZ, (float) box.minX, (float) box.minY, (float) box.minZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.minX, (float) box.minY, (float) box.minZ, (float) box.minX, (float) box.maxY, (float) box.minZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.maxX, (float) box.minY, (float) box.minZ, (float) box.maxX, (float) box.maxY, (float) box.minZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.maxX, (float) box.minY, (float) box.maxZ, (float) box.maxX, (float) box.maxY, (float) box.maxZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.minX, (float) box.minY, (float) box.maxZ, (float) box.minX, (float) box.maxY, (float) box.maxZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.minX, (float) box.maxY, (float) box.minZ, (float) box.maxX, (float) box.maxY, (float) box.minZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.maxX, (float) box.maxY, (float) box.minZ, (float) box.maxX, (float) box.maxY, (float) box.maxZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.maxX, (float) box.maxY, (float) box.maxZ, (float) box.minX, (float) box.maxY, (float) box.maxZ, color); + buildLine3d(matrices, bufferBuilder, (float) box.minX, (float) box.maxY, (float) box.maxZ, (float) box.minX, (float) box.maxY, (float) box.minZ, color); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); + + RenderSystem.enableCull(); + RenderSystem.lineWidth(1f); + RenderSystem.enableDepthTest(); + RenderSystem.disableBlend(); + } + + public static void draw3DBox(MatrixStack matrixStack, Box box, Color color, float lineThickness) { + RenderSystem.setShaderColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + + MatrixStack.Entry entry = matrixStack.peek(); + Matrix4f matrix4f = entry.getPositionMatrix(); + + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.disableCull(); + RenderSystem.disableDepthTest(); + + RenderSystem.setShader(ShaderProgramKeys.POSITION); + + RenderSystem.setShaderColor(color.getRed(), color.getGreen(), color.getBlue(), 0.5F); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION); + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.minY, (float) box.minZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.minY, (float) box.minZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.minY, (float) box.maxZ); + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.minY, (float) box.maxZ); + + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.maxY, (float) box.minZ); + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.maxY, (float) box.maxZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.maxY, (float) box.maxZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.maxY, (float) box.minZ); + + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.minY, (float) box.minZ); + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.maxY, (float) box.minZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.maxY, (float) box.minZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.minY, (float) box.minZ); + + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.minY, (float) box.minZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.maxY, (float) box.minZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.maxY, (float) box.maxZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.minY, (float) box.maxZ); + + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.minY, (float) box.maxZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.minY, (float) box.maxZ); + bufferBuilder.vertex(matrix4f, (float) box.maxX, (float) box.maxY, (float) box.maxZ); + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.maxY, (float) box.maxZ); + + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.minY, (float) box.minZ); + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.minY, (float) box.maxZ); + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.maxY, (float) box.maxZ); + bufferBuilder.vertex(matrix4f, (float) box.minX, (float) box.maxY, (float) box.minZ); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + RenderSystem.setShaderColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + + RenderSystem.setShader(ShaderProgramKeys.RENDERTYPE_LINES); + + RenderSystem.lineWidth(lineThickness); + + bufferBuilder = tessellator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES); + + buildLine3d(matrixStack, bufferBuilder, (float) box.minX, (float) box.minY, (float) box.minZ, (float) box.maxX, + (float) box.minY, (float) box.minZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.maxX, (float) box.minY, (float) box.minZ, (float) box.maxX, + (float) box.minY, (float) box.maxZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.maxX, (float) box.minY, (float) box.maxZ, (float) box.minX, + (float) box.minY, (float) box.maxZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.minX, (float) box.minY, (float) box.maxZ, (float) box.minX, + (float) box.minY, (float) box.minZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.minX, (float) box.minY, (float) box.minZ, (float) box.minX, + (float) box.maxY, (float) box.minZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.maxX, (float) box.minY, (float) box.minZ, (float) box.maxX, + (float) box.maxY, (float) box.minZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.maxX, (float) box.minY, (float) box.maxZ, (float) box.maxX, + (float) box.maxY, (float) box.maxZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.minX, (float) box.minY, (float) box.maxZ, (float) box.minX, + (float) box.maxY, (float) box.maxZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.minX, (float) box.maxY, (float) box.minZ, (float) box.maxX, + (float) box.maxY, (float) box.minZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.maxX, (float) box.maxY, (float) box.minZ, (float) box.maxX, + (float) box.maxY, (float) box.maxZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.maxX, (float) box.maxY, (float) box.maxZ, (float) box.minX, + (float) box.maxY, (float) box.maxZ, color); + buildLine3d(matrixStack, bufferBuilder, (float) box.minX, (float) box.maxY, (float) box.maxZ, (float) box.minX, + (float) box.maxY, (float) box.minZ, color); + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + + RenderSystem.enableCull(); + RenderSystem.lineWidth(1f); + RenderSystem.enableDepthTest(); + RenderSystem.disableBlend(); + + } + + public static void drawLineToEntity(MatrixStack matrices, PlayerEntity player, Entity entity, float delta, Color color, float lineWidth) { + Vec3d playerPos = getEntityPositionInterpolated(player, delta); + Vec3d entityPos = getEntityPositionInterpolated(entity, delta); + + + Vec3d cameraPos = MinecraftClient.getInstance().gameRenderer.getCamera().getPos(); + + float x1 = (float) (playerPos.x - cameraPos.x); + float y1 = (float) (playerPos.y - cameraPos.y); + float z1 = (float) (playerPos.z - cameraPos.z); + + float x2 = (float) (entityPos.x - cameraPos.x); + float y2 = (float) (entityPos.y - cameraPos.y); + float z2 = (float) (entityPos.z - cameraPos.z); + + Render3D.drawLine3D(matrices, x1, y1, z1, x2, y2, z2, color, 5.0f); + } + + public static void drawLineToBlockEntity(MatrixStack matrices, PlayerEntity player, BlockEntity blockEntity, float delta, Color color, float lineWidth) { + Vec3d playerPos = getEntityPositionInterpolated(player, delta); + Vec3d blockPos = new Vec3d( + blockEntity.getPos().getX() + 0.5, + blockEntity.getPos().getY() + 0.5, + blockEntity.getPos().getZ() + 0.5 + ); + + Vec3d cameraPos = MinecraftClient.getInstance().gameRenderer.getCamera().getPos(); + + float x1 = (float) (playerPos.x - cameraPos.x); + float y1 = (float) (playerPos.y - cameraPos.y); + float z1 = (float) (playerPos.z - cameraPos.z); + + float x2 = (float) (blockPos.x - cameraPos.x); + float y2 = (float) (blockPos.y - cameraPos.y); + float z2 = (float) (blockPos.z - cameraPos.z); + + Render3D.drawLine3D(matrices, x1, y1, z1, x2, y2, z2, color, lineWidth); + } + + public static Vec3d rotateVector(Vec3d vec, double yaw, double pitch) { + double cosYaw = Math.cos(Math.toRadians(-yaw)); + double sinYaw = Math.sin(Math.toRadians(-yaw)); + + double rotatedX = cosYaw * vec.x - sinYaw * vec.z; + double rotatedZ = sinYaw * vec.x + cosYaw * vec.z; + + double cosPitch = Math.cos(Math.toRadians(-pitch)); + double sinPitch = Math.sin(Math.toRadians(-pitch)); + + double rotatedY = cosPitch * vec.y - sinPitch * rotatedZ; + rotatedZ = sinPitch * vec.y + cosPitch * rotatedZ; + + return new Vec3d(rotatedX, rotatedY, rotatedZ); + } + + public static void drawLine3D(MatrixStack matrixStack, Vec3d pos1, Vec3d pos2, Color color, float lineWidth) { + drawLine3D(matrixStack, (float) pos1.x, (float) pos1.y, (float) pos1.z, (float) pos2.x, (float) pos2.y, + (float) pos2.z, color, lineWidth); + } + + public static void drawLine3D(MatrixStack matrices, float x1, float y1, float z1, float x2, float y2, float z2, + Color color, float lineWidth) { + + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.disableCull(); + RenderSystem.disableDepthTest(); + + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + RenderSystem.setShaderColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + + RenderSystem.setShader(ShaderProgramKeys.RENDERTYPE_LINES); + RenderSystem.lineWidth(lineWidth); + + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES); + buildLine3d(matrices, bufferBuilder, x1, y1, z1, x2, y2, z2, color); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + RenderSystem.enableCull(); + RenderSystem.lineWidth(1f); + RenderSystem.enableDepthTest(); + RenderSystem.disableBlend(); + } + + public static void drawWorldText(WorldRenderContext context, String text, Vec3d entityPos, Color color, float scale) { + MinecraftClient client = MinecraftClient.getInstance(); + MatrixStack matrices = context.matrixStack(); + Vec3d cameraPos = context.camera().getPos(); + VertexConsumerProvider.Immediate consumerProvider = (VertexConsumerProvider.Immediate) context.consumers(); + DrawContext drawContext = new DrawContext(client, consumerProvider); + + double x = entityPos.x - cameraPos.x; + double y = entityPos.y - cameraPos.y; + double z = entityPos.z - cameraPos.z; + + if (z < 0) return; + + matrices.push(); + + matrices.translate(x, y, z); + + Quaternionf rotation = new Quaternionf() + .rotateY((float) Math.toRadians(-context.camera().getYaw())) + .rotateX((float) Math.toRadians(context.camera().getPitch())); + + matrices.multiply(rotation); + + float distance = (float) client.player.squaredDistanceTo(entityPos); + float textScale = Math.max(0.02F, scale / (distance * 0.1F)); + matrices.scale(-textScale, -textScale, textScale); + + drawContext.drawText(client.textRenderer, text, -client.textRenderer.getWidth(text) / 2, 0, color.getColorAsInt(), false); + + matrices.pop(); + } + + private static float getYaw(Direction direction) { + return switch (direction) + { + case SOUTH -> 90.0f; + case WEST -> 0.0f; + case NORTH -> 270.0f; + case EAST -> 180.0f; + default -> 0.0f; + }; + } + + private static void buildLine3d(MatrixStack matrices, BufferBuilder bufferBuilder, float x1, float y1, float z1, float x2, float y2, float z2, Color color) { + MatrixStack.Entry entry = matrices.peek(); + Matrix4f matrix4f = entry.getPositionMatrix(); + + Vec3d normalized = new Vec3d(x2 - x1, y2 - y1, z2 - z1).normalize(); + + float r = color.getRed(); + float g = color.getGreen(); + float b = color.getBlue(); + + bufferBuilder.vertex(matrix4f, x1, y1, z1).color(r, g, b, 1.0f).normal(entry, (float) normalized.x, + (float) normalized.y, (float) normalized.z); + bufferBuilder.vertex(matrix4f, x2, y2, z2).color(r, g, b, 1.0f).normal(entry, (float) normalized.x, + (float) normalized.y, (float) normalized.z); + } + + public static Vec3d getEntityPositionInterpolated(Entity entity, float delta) { + return new Vec3d(MathHelper.lerp(delta, entity.prevX, entity.getX()), + MathHelper.lerp(delta, entity.prevY, entity.getY()), + MathHelper.lerp(delta, entity.prevZ, entity.getZ())); + } + + public static Vec3d getEntityPositionOffsetInterpolated(Entity entity, float delta) { + Vec3d interpolated = getEntityPositionInterpolated(entity, delta); + return entity.getPos().subtract(interpolated); + } +} \ No newline at end of file diff --git a/src/main/java/online/bobtony/utils/render/WorldToScreen.java b/src/main/java/online/bobtony/utils/render/WorldToScreen.java new file mode 100644 index 0000000..7a6d595 --- /dev/null +++ b/src/main/java/online/bobtony/utils/render/WorldToScreen.java @@ -0,0 +1,39 @@ +package online.bobtony.utils.render; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.Camera; +import net.minecraft.util.math.Vec3d; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.joml.Vector4f; + +public class WorldToScreen { + public static final Matrix4f lastProjMat = new Matrix4f(); + public static final Matrix4f lastModMat = new Matrix4f(); + public static final Matrix4f lastWorldSpaceMatrix = new Matrix4f(); + public static final int[] lastViewport = new int[4]; + private static final MinecraftClient client = MinecraftClient.getInstance(); + + public static Vec3d worldSpaceToScreenSpace(Vec3d pos) { + Camera camera = client.getEntityRenderDispatcher().camera; + int displayHeight = client.getWindow().getHeight(); + 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; + + Vector4f transformedCoordinates = new Vector4f((float) deltaX, (float) deltaY, (float) deltaZ, 1.f).mul(lastWorldSpaceMatrix); + + Matrix4f matrixProj = new Matrix4f(lastProjMat); + Matrix4f matrixModel = new Matrix4f(lastModMat); + + matrixProj.mul(matrixModel).project(transformedCoordinates.x(), transformedCoordinates.y(), transformedCoordinates.z(), lastViewport, target); + + return new Vec3d(target.x / client.getWindow().getScaleFactor(), (displayHeight - target.y) / client.getWindow().getScaleFactor(), target.z); + } + + public static boolean screenSpaceCoordinateIsVisible(Vec3d pos) { + return pos != null && pos.z > -1 && pos.z < 1; + } +} \ No newline at end of file diff --git a/src/main/resources/assets/bobtony/font/iconfont_2.json b/src/main/resources/assets/bobtony/font/iconfont_2.json new file mode 100644 index 0000000..a6dd40e --- /dev/null +++ b/src/main/resources/assets/bobtony/font/iconfont_2.json @@ -0,0 +1,19 @@ +{ + "providers": [ + { + "type": "bitmap", + "file": "bobtony:iconfont/rank_icons_2.png", + "ascent": 7, + "height": 7, + "chars": [ + "", + "", + "", + "", + "", + "", + "" + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/bobtony/lang/en_us.json b/src/main/resources/assets/bobtony/lang/en_us.json new file mode 100644 index 0000000..3e464b9 --- /dev/null +++ b/src/main/resources/assets/bobtony/lang/en_us.json @@ -0,0 +1,4 @@ +{ + "bobtony.switchmodes": "Switch Modes", + "bobtony.zoom": "Zoom" +} \ No newline at end of file diff --git a/src/main/resources/assets/bobtony/textures/iconfont/rank_icons_2.png b/src/main/resources/assets/bobtony/textures/iconfont/rank_icons_2.png new file mode 100644 index 0000000..a8cd5a6 Binary files /dev/null and b/src/main/resources/assets/bobtony/textures/iconfont/rank_icons_2.png differ diff --git a/src/main/resources/bobtony.mixins.json b/src/main/resources/bobtony.mixins.json new file mode 100644 index 0000000..fdb5c26 --- /dev/null +++ b/src/main/resources/bobtony.mixins.json @@ -0,0 +1,20 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "online.bobtony.mixin", + "compatibilityLevel": "JAVA_21", + "mixins": [ + "ServerPlayNetworkHanderMixin" + ], + "client": [ + "AbstractClientPlayerEntityMixin", + "ClientPlayerEntityMixin", + "EntityRendererMixin", + "GameRendererMixin", + "TitleScreenMixin", + "PlayerListEntryMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..dfa284b --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,25 @@ +{ + "schemaVersion": 1, + "id": "bobtony", + "version": "${version}", + "name": "BobTony", + "description": "BobTony", + "authors": ["BobTonyTeam"], + "contact": {}, + "license": "All-Rights-Reserved", + "icon": "assets/bobtony/icon.png", + "environment": "client", + "entrypoints": { + "client": [ + "online.bobtony.BobtonyClient" + ] + }, + "mixins": [ + "bobtony.mixins.json" + ], + "depends": { + "fabricloader": ">=${loader_version}", + "fabric": "*", + "minecraft": "${minecraft_version}" + } +}