From 64c060edb554a90043897eb07732b75efada1a6c Mon Sep 17 00:00:00 2001 From: Flummi Date: Sun, 4 Jun 2023 13:24:56 +0200 Subject: [PATCH] first commit --- .gitignore | 34 ++ README.md | 0 build.gradle | 80 +++++ gradle.properties | 17 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 62076 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 245 ++++++++++++++ settings.gradle | 10 + .../skilloverlay/api/PlayerProfile.java | 52 +++ .../skilloverlay/api/records/Enchanting.java | 26 ++ .../skilloverlay/api/records/Farming.java | 30 ++ .../skilloverlay/api/records/Items.java | 52 +++ .../api/records/PlayerProfiles.java | 164 ++++++++++ .../skilloverlay/api/records/Slayer.java | 29 ++ .../api/records/dungeons/Dungeons.java | 40 +++ .../api/records/dungeons/Floor.java | 44 +++ .../api/records/dungeons/Journals.java | 18 ++ .../skilloverlay/api/records/mining/Core.java | 41 +++ .../api/records/mining/Mining.java | 18 ++ .../api/records/misc/Burrows.java | 19 ++ .../skilloverlay/api/records/misc/Misc.java | 42 +++ .../skilloverlay/mixin/GameRenderMixin.java | 25 ++ .../skilloverlay/overlays/FarmingOverlay.java | 306 ++++++++++++++++++ .../overlays/FarmingOverlay.java.unused | 73 +++++ .../lel/flummi/skilloverlay/skilloverlay.java | 23 ++ .../flummi/skilloverlay/utils/LerpUtils.java | 24 ++ .../resources/assets/skilloverlay/icon.png | Bin 0 -> 453 bytes src/main/resources/fabric.mod.json | 34 ++ src/main/resources/skilloverlay.mixins.json | 11 + 29 files changed, 1463 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 settings.gradle create mode 100644 src/main/java/lel/flummi/skilloverlay/api/PlayerProfile.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/Enchanting.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/Farming.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/Items.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/PlayerProfiles.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/Slayer.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Dungeons.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Floor.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Journals.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/mining/Core.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/mining/Mining.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/misc/Burrows.java create mode 100644 src/main/java/lel/flummi/skilloverlay/api/records/misc/Misc.java create mode 100644 src/main/java/lel/flummi/skilloverlay/mixin/GameRenderMixin.java create mode 100644 src/main/java/lel/flummi/skilloverlay/overlays/FarmingOverlay.java create mode 100644 src/main/java/lel/flummi/skilloverlay/overlays/FarmingOverlay.java.unused create mode 100644 src/main/java/lel/flummi/skilloverlay/skilloverlay.java create mode 100644 src/main/java/lel/flummi/skilloverlay/utils/LerpUtils.java create mode 100644 src/main/resources/assets/skilloverlay/icon.png create mode 100644 src/main/resources/fabric.mod.json create mode 100644 src/main/resources/skilloverlay.mixins.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..896dca7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# gradle + +.gradle/ +build/ +out/ +classes/ +logs/ + +# eclipse + +*.launch + +# idea + +.idea/ +*.iml +*.ipr +*.iws + +# vscode + +.settings/ +.vscode/ +bin/ +.classpath +.project + +# macos + +*.DS_Store + +# fabric + +run/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..eaef946 --- /dev/null +++ b/build.gradle @@ -0,0 +1,80 @@ +plugins { + id 'fabric-loom' version '1.2-SNAPSHOT' + id 'maven-publish' +} + +version = "${project.mod_version}+${project.minecraft_version}" +group = project.maven_group + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +dependencies { + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" +} + +base { + archivesName = project.archives_base_name +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +tasks.withType(JavaCompile).configureEach { + // ensure that the encoding is set to UTF-8, no matter what the system default is + // this fixes some edge cases with special characters not displaying correctly + // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html + // If Javadoc is generated, this must be specified in that task too. + + + // Minecraft 1.18 upwards uses Java 17. + it.options.release = 17 +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +jar { + from("LICENSE") { + rename { "${it}_${base.archivesName.get()}"} + } +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..7825b5e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G +org.gradle.parallel=true + +# Fabric Properties +# check these on https://fabricmc.net/develop +minecraft_version=1.19.4 +yarn_mappings=1.19.4+build.2 +loader_version=0.14.20 + +# Mod Properties +mod_version = 1.0.0 +maven_group = lel.flummi +archives_base_name = skilloverlay + +# Dependencies +fabric_version=0.79.0+1.19.4 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..c1962a79e29d3e0ab67b14947c167a862655af9b GIT binary patch literal 62076 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 X8Q{&z2GVKHV9uZ{%)sD$AH)LyV59Xb literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..37aef8d --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..aeb74cb --- /dev/null +++ b/gradlew @@ -0,0 +1,245 @@ +#!/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. +# + +############################################################################## +# +# 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/subprojects/plugins/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##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || 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 + which java >/dev/null 2>&1 || 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 + +# 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=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=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, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +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/settings.gradle b/settings.gradle new file mode 100644 index 0000000..b02216b --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + mavenCentral() + gradlePluginPortal() + } +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/PlayerProfile.java b/src/main/java/lel/flummi/skilloverlay/api/PlayerProfile.java new file mode 100644 index 0000000..1dabb91 --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/PlayerProfile.java @@ -0,0 +1,52 @@ +package lel.flummi.skilloverlay.api; + +import net.minecraft.client.MinecraftClient; + +import lel.flummi.skilloverlay.api.records.PlayerProfiles; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.InputStreamReader; +import java.net.URL; +import java.util.Timer; +import java.util.TimerTask; + +public class PlayerProfile { + public static PlayerProfiles.PlayerProfile PROFILE; + + public static void init() { + Timer timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + PlayerProfiles profiles = PlayerProfile.updateProfile(); + + PlayerProfiles.PlayerProfile currentProfile = profiles.profiles().get(""); + + for (PlayerProfiles.PlayerProfile profile: profiles.profiles().values()) { + if(profile.current() == true) { + currentProfile = profile; + } + } + + PROFILE = currentProfile; + } + }, 0, 60 * 1000); + } + + public static PlayerProfiles updateProfile() { + try { + URL url = new URL("https://sky.shiiyu.moe/api/v2/profile/" + MinecraftClient.getInstance().getSession().getUsername()); + InputStreamReader reader = new InputStreamReader(url.openStream()); + Gson gson = new GsonBuilder() + .serializeNulls() + .create(); + return gson.fromJson(reader, PlayerProfiles.class); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/Enchanting.java b/src/main/java/lel/flummi/skilloverlay/api/records/Enchanting.java new file mode 100644 index 0000000..fe1a41d --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/Enchanting.java @@ -0,0 +1,26 @@ +package lel.flummi.skilloverlay.api.records; + +import com.google.gson.annotations.SerializedName; + +import java.util.HashMap; + +public record Enchanting(boolean experimented, HashMap experiments){ + public record Experiment( + String name, + Stats stats, + Tier[] tiers + + ){ + public record Stats( + @SerializedName("last_attempt") PlayerProfiles.PlayerProfile.Data.LastUpdated lastAttempt, + @SerializedName("bonus_clicks") int bonusClicks, + @SerializedName("last_claimed") PlayerProfiles.PlayerProfile.Data.LastUpdated lastClaimed + ){} + public record Tier( + String name, + int attempts, + int claims, + @SerializedName("best_score") int bestScore + ){} + } +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/Farming.java b/src/main/java/lel/flummi/skilloverlay/api/records/Farming.java new file mode 100644 index 0000000..0496d17 --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/Farming.java @@ -0,0 +1,30 @@ +package lel.flummi.skilloverlay.api.records; + +import com.google.gson.annotations.SerializedName; + +import java.util.HashMap; + +public record Farming( + boolean talked, + @SerializedName("current_badges") Badges currentBadges, + @SerializedName("total_badges") Badges totalBadges, + Perks perks, + @SerializedName("unique_golds") int unique_golds, + HashMap crops, + Contests contests +){ + public record Badges(int bronze, int silver, int gold){} + public record Perks(@SerializedName("double_drops") int doubleDrops, @SerializedName("farming_level_cap") int farmingLevelCap){} + public record Crop( + String name, + boolean attended, + @SerializedName("unique_gold") boolean uniqueGold, + int contests, + @SerializedName("personal_best") int personalBest, + Badges badges + ){} + public record Contests(@SerializedName("attended_contests") int attendedContests, @SerializedName("all_contests") Contest[] allContests){} + public record Contest(String date, String crop, int collected, boolean claimed, String medal, Placing placing){ + public record Placing(int position, double percentage){} + } +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/Items.java b/src/main/java/lel/flummi/skilloverlay/api/records/Items.java new file mode 100644 index 0000000..f8ea01d --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/Items.java @@ -0,0 +1,52 @@ +package lel.flummi.skilloverlay.api.records; + +import com.google.gson.annotations.SerializedName; + +import java.util.HashMap; + +public record Items( + Item[] armor, + Item[][] wardrobe, + Item[] inventory, + Item[] enderchest, + @SerializedName("talisman_bag") Item[] talismanBag, + @SerializedName("fishing_bag") Item[] fishingBag, + Item[] quiver, + @SerializedName("potion_bag") Item[] potionBag, + @SerializedName("personal_vault") Item[] personalVault, + Item[] storage, + Item[] weapons, + Item[] hoes, + Item[] pickaxes, + Item[] rods, + @SerializedName("highest_rarity_sword") Item highestRaritySword, + @SerializedName("highest_rarity_bow") Item highestRarityBow, + @SerializedName("highest_rarity_rod") Item highestRarityRod, + @SerializedName("armor_set_rarity") String armorSetRarity +){ + public record Item( + @SerializedName("Count") byte count, + int damage, + Tag tag, + boolean isInactive, + boolean inBackpack, + Item[] containsItems + ){ + public record Tag( + @SerializedName("ExtraAttributes") ExtraAttributes extraAttributes, + Display display, + @SerializedName("SkullOwner") SkullOwner skullOwner, + Enchant[] ench + ){ + public record ExtraAttributes(String id, HashMap enchantments){} + public record Display(@SerializedName("Name") String name, @SerializedName("Lore") String[] lore, Integer color){} + public record SkullOwner( + @SerializedName("Id") String id, + @SerializedName("Properties") Properties properties + ){ + public record Properties(HashMap[] textures){} + } + public record Enchant(int lvl, int id){} + } + } +} \ No newline at end of file diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/PlayerProfiles.java b/src/main/java/lel/flummi/skilloverlay/api/records/PlayerProfiles.java new file mode 100644 index 0000000..8f26659 --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/PlayerProfiles.java @@ -0,0 +1,164 @@ +package lel.flummi.skilloverlay.api.records; + +import lel.flummi.skilloverlay.api.records.dungeons.Dungeons; +import lel.flummi.skilloverlay.api.records.mining.Mining; +import lel.flummi.skilloverlay.api.records.misc.Misc; + +import com.google.gson.annotations.SerializedName; +import java.util.HashMap; + +public record PlayerProfiles(HashMap profiles) { + public record PlayerProfile( + @SerializedName("profile_id") String profileId, + @SerializedName("cute_name") String cuteName, + boolean current, + @SerializedName("last_save") long lastSave, + Items items, + Data data) { + public record Data( + Stats stats, + @SerializedName("fairy_bonus") Stats fairyBonus, + @SerializedName("fairy_souls") FairySouls fairySouls, + @SerializedName("levels") HashMap skills, + @SerializedName("average_level") double averageLevel, + @SerializedName("average_level_no_progress") double trueAverageLevel, + @SerializedName("total_skill_xp") double totalSkillXp, + @SerializedName("skill_bonus") HashMap skillBonus, + @SerializedName("average_level_rank") double averageLevelRank, + @SerializedName("slayer_coins_spent") HashMap slayerCoinsSpent, + @SerializedName("slayer_bonus") HashMap slayerBonus, + HashMap slayers, + @SerializedName("slayer_xp") int slayerXp, + @SerializedName("display_name") String username, + String uuid, + double bank, + double purse, + @SerializedName("current_area") String currentArea, + Entity[] kills, + Entity[] deaths, + @SerializedName("wardrobe_equipped_slot") int wardrobeEquippedSlot, + @SerializedName("skin_data") SkinData skinData, + Profile profile, + Member[] members, + Minion[] minions, + @SerializedName("minion_slots") MinionSlots minionSlots, + HashMap collections, + Social social, + Dungeons dungeons, + Fishing fishing, + Farming farming, + Enchanting Enchanting, + Mining mining, + Misc misc, + @SerializedName("auctions_bought") Auctions auctionsBought, + @SerializedName("auctions_sold") Auctions auctionsSold, + @SerializedName("last_updated") LastUpdated lastUpdated, + @SerializedName("first_join") LastUpdated firstJoin + ) { + public record Stats( + int health, + int defense, + @SerializedName("effective_health") int effectiveHealth, + int strength, + int speed, + @SerializedName("crit_chance") double critChance, + @SerializedName("crit_damage") int critDamage, + @SerializedName("bonus_attack_speed") int bonusAttackSpeed, + int intelligence, + @SerializedName("sea_creature_chance") int seaCreatureChance, + @SerializedName("magic_find") int magicFind, + @SerializedName("pet_luck") int petLuck, + int ferocity, + @SerializedName("ability_damage") double abilityDamage, + @SerializedName("mining_speed") int miningSpeed, + @SerializedName("mining_fortune") int miningFortune, + @SerializedName("farming_fortune") int farmingFortune, + @SerializedName("foraging_fortune") int foragingFortune, + int pristine, + int damage, + @SerializedName("damage_increase") double damageIncrease) { + } + + public record FairySouls(int collected, int total, double progress) { + } + + public record Level( + Double xp, + Integer level, + Integer maxLevel, + Long xpCurrent, + Integer xpForNext, + Double progress, + Integer levelCap, + Integer uncappedLevel, + Integer rank, + Double levelWithProgress, + Double unlockableLevelWithProgress) { + } + + public record Entity(String type, String entityId, int amount, String entityName) { + } + + public record SkinData(@SerializedName("skinurl") String skinUrl, String model) { + } + + public record Profile(String gamemode) { + } + + public record Member( + String uuid, + @SerializedName("display_name") String displayName, + @SerializedName("last_updated") LastUpdated lastUpdated, + @SerializedName("skin_data") SkinData skinData) { + } + + public record LastUpdated(long unix, String text) { + } + + public record Minion( + String id, + String type, + int tiers, + String name, + Integer[] levels + + ) { + } + + public record MinionSlots(int currentSlots, int toNext, int toNextSlot) { + } + + public record Collection(int tier, long amount, long totalAmount, UserAmount[] amounts) { + public record UserAmount(String username, long amount) { + } + } + + public record Social( + @SerializedName("DISCORD") String discord, + @SerializedName("HYPIXEL") String hypixel, + @SerializedName("TWITTER") String twitter, + @SerializedName("YOUTUBE") String youtube, + @SerializedName("INSTAGRAM") String instagram, + @SerializedName("TWITCH") String twitch) { + } + + public record Fishing( + int total, + int treasure, + @SerializedName("treasure_large") int treasureLarge, + @SerializedName("shredder_fished") int shredderFished, + @SerializedName("shredder_bait") int shredderBait) { + } + + public record Auctions( + int uncommon, + int rare, + int epic, + int common, + int legendary, + int special) { + } + } + + } +} \ No newline at end of file diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/Slayer.java b/src/main/java/lel/flummi/skilloverlay/api/records/Slayer.java new file mode 100644 index 0000000..3b2b9bb --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/Slayer.java @@ -0,0 +1,29 @@ +package lel.flummi.skilloverlay.api.records; + +import com.google.gson.annotations.SerializedName; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; + +public record Slayer( + PlayerProfiles.PlayerProfile.Data.Level level, + Kills kills, + @SerializedName("claimed_levels") ClaimedLevels claimedLevels, + int xp, + @SerializedName("boss_kills_tier_0") int bossKillsTier0, + @SerializedName("boss_kills_tier_1") int bossKillsTier1, + @SerializedName("boss_kills_tier_2") int bossKillsTier2, + @SerializedName("boss_kills_tier_3") int bossKillsTier3 +){ + public record Kills(@Nullable HashMap kills){} + public record ClaimedLevels( + @SerializedName("level_1") boolean level1, + @SerializedName("level_2") boolean level2, + @SerializedName("level_3") boolean level3, + @SerializedName("level_4") boolean level4, + @SerializedName("level_5") boolean level5, + @SerializedName("level_6") boolean level6, + @SerializedName("level_7_special") boolean level7 + ){} + +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Dungeons.java b/src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Dungeons.java new file mode 100644 index 0000000..c189e90 --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Dungeons.java @@ -0,0 +1,40 @@ +package lel.flummi.skilloverlay.api.records.dungeons; + +import com.google.gson.annotations.SerializedName; +import lel.flummi.skilloverlay.api.records.PlayerProfiles; + +import java.util.HashMap; + +public record Dungeons( + Dungeon catacombs, + @SerializedName("master_catacombs") Dungeon masterCatacombs, + HashMap classes, + @SerializedName("used_classes") boolean usedClasses, + @SerializedName("selected_class") String selectedClass, + @SerializedName("secrets_found") int secretsFound, + HashMap essence, + @SerializedName("unlocked_collections") boolean unlockedCollections, + @SerializedName("boss_collections") HashMap bossCollections + //Journals journals + +){ + public record Dungeon( + String id, + boolean visited, + PlayerProfiles.PlayerProfile.Data.Level level, + @SerializedName("highest_floor") String highestFloor, + HashMap floors + + ){} + public record Collection( + String name, + String texture, + int tier, + boolean maxed, + int killed, + HashMap floors, + int unclaimed, + String[] claimed + ){} + public record Class(PlayerProfiles.PlayerProfile.Data.Level experience, boolean current){} +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Floor.java b/src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Floor.java new file mode 100644 index 0000000..a28304c --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Floor.java @@ -0,0 +1,44 @@ +package lel.flummi.skilloverlay.api.records.dungeons; + +import com.google.gson.annotations.SerializedName; + +public record Floor( + String name, + Stats stats, + @SerializedName("most_damage") MostDamage mostDamage, + Bonuses bonuses + +){ + public record Stats( + @SerializedName("times_played") int timesPlayed, + @SerializedName("best_score") int bestScore, + @SerializedName("mobs_killed") int mobsKilled, + @SerializedName("most_mobs_killed") int mostMobsKilled, + @SerializedName("most_healing") double mostHealing, + @SerializedName("tier_completions") int tierCompletions, + @SerializedName("fastest_time") long fastestTime, + @SerializedName("watcher_kills") int watcherKills, + @SerializedName("best_runs") Run[] bestRuns + ){} + public record MostDamage( + @SerializedName("class") String classUsed, + @SerializedName("value") double damage + ){} + public record Run( + long timestamp, + @SerializedName("score_exploration") int scoreExploration, + @SerializedName("score_speed") int scoreSpeed, + @SerializedName("score_skill") int scoreSkill, + @SerializedName("score_bonus") int scoreBonus, + @SerializedName("dungeon_class") int dungeonClass, + String[] teammates, + @SerializedName("elapsed_time") long elapsedTime, + @SerializedName("damaged_dealt") int damageDealt, + int deaths, + @SerializedName("mobs_killed") int mobsKilled, + @SerializedName("secrets_found") int secretsFound, + @SerializedName("damage_mitigated") double damageMitigated, + @SerializedName("ally_healing") int allyHealing + ){} + public record Bonuses(@SerializedName("item_boost") int itemBoost){} +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Journals.java b/src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Journals.java new file mode 100644 index 0000000..22ed2ad --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/dungeons/Journals.java @@ -0,0 +1,18 @@ +package lel.flummi.skilloverlay.api.records.dungeons; + +import com.google.gson.annotations.SerializedName; + +public record Journals( + @SerializedName("pages_completed") int pagesCompleted, + @SerializedName("journals_completed") int journalsCompleted, + @SerializedName("total_pages") Integer totalPages, + boolean maxed, + @SerializedName("journal_entries") Entry[] journalEntries + +){ + public record Entry( + String name, + @SerializedName("pages_collected") int pagesCollected, + @SerializedName("total_pages") Integer totalPages + ){} +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/mining/Core.java b/src/main/java/lel/flummi/skilloverlay/api/records/mining/Core.java new file mode 100644 index 0000000..924e6c1 --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/mining/Core.java @@ -0,0 +1,41 @@ +package lel.flummi.skilloverlay.api.records.mining; + +import com.google.gson.annotations.SerializedName; +import lel.flummi.skilloverlay.api.records.PlayerProfiles; + +import java.util.HashMap; + +public record Core( + PlayerProfiles.PlayerProfile.Data.Level tier, + Spent tokens, + @SerializedName("selected_pickaxe_ability") String selectedMiningAbility, + HashMap powder, + @SerializedName("crystal_nucleus") Nucleus crystalNucleus, + @SerializedName("daily_ores") DailyOres dailyOres, + @SerializedName("hotm_last_reset") long hotmLastReset, + @SerializedName("crystal_hollows_last_access") long crystalHollowsLastAccess +){ + public record Spent(int total, int spent, int available){} + public record Nucleus( + @SerializedName("times_completed") int timesCompleted, + HashMap crystals, + Goblin goblin + ){ + public record Crystal( + String state, + @SerializedName("total_placed") int totalPlaced, + @SerializedName("total_found") int totalFound + ){} + public record Goblin( + @SerializedName("king_quest_active") boolean kingQuestActive, + @SerializedName("king_quest_completed") boolean kingQuestCompleted + ){} + } + public record DailyOres( + int mined, + int day, + @SerializedName("daily_ores") HashMap dailyOres + ){ + public record Ore(int day, int count){} + } +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/mining/Mining.java b/src/main/java/lel/flummi/skilloverlay/api/records/mining/Mining.java new file mode 100644 index 0000000..c82b2e9 --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/mining/Mining.java @@ -0,0 +1,18 @@ +package lel.flummi.skilloverlay.api.records.mining; + +public record Mining( + Commissions commissions, + Forge forge, + Core core +){ + public record Forge(Process[] processes){ + public record Process( + String id, + int slot, + long timeFinished, + String timeFinishedText, + String name + ){} + } + public record Commissions(int milestone){} +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/misc/Burrows.java b/src/main/java/lel/flummi/skilloverlay/api/records/misc/Burrows.java new file mode 100644 index 0000000..60ae510 --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/misc/Burrows.java @@ -0,0 +1,19 @@ +package lel.flummi.skilloverlay.api.records.misc; + +import com.google.gson.annotations.SerializedName; + +public record Burrows( + @SerializedName("dug_next") Rarities dugNext, + @SerializedName("dug_combat") Rarities dugCombat, + @SerializedName("dug_treasure") Rarities dugTreasure, + @SerializedName("chains_complete") Rarities chainsComplete +){ + public record Rarities( + int total, + @SerializedName("null") int common, + int uncommon, + int rare, + int epic, + int legendary + ){} +} diff --git a/src/main/java/lel/flummi/skilloverlay/api/records/misc/Misc.java b/src/main/java/lel/flummi/skilloverlay/api/records/misc/Misc.java new file mode 100644 index 0000000..26861ae --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/api/records/misc/Misc.java @@ -0,0 +1,42 @@ +package lel.flummi.skilloverlay.api.records.misc; + +import com.google.gson.annotations.SerializedName; + +public record Misc( + Milestones milestones, + Gifts gifts, + Winter winter, + Dragons dragons, + Protector protector, + Damage damage, + Burrows burrows, + ProfileUpgrades profileUpgrades +){ + public record Milestones( + @SerializedName("ores_mined") int oresMined, + @SerializedName("sea_creatures_killed") int seaCreaturesKilled + ){} + public record Gifts(@SerializedName("gifts_given") int giftsGiven){} + public record Winter( + @SerializedName("most_winter_snowballs_hit") int mostWinterSnowballsHit, + @SerializedName("most_winter_damage_dealt") int mostWinterDamageDealt, + @SerializedName("most_winter_magma_damage_dealt") int mostWinterMagmaDamageDealt + ){} + public record Dragons( + @SerializedName("ender_crystals_destroyed") int enderCrystalsDestroyed, + @SerializedName("last_hits") int lastHits, + @SerializedName("deaths") int deaths + ){} + public record Protector( + @SerializedName("last_hits") int lastHits, + int deaths + ){} + public record Damage(@SerializedName("highest_critical_damage") double highestCriticalDamage){} + public record ProfileUpgrades( + @SerializedName("island_size") int islandSize, + @SerializedName("minion_slots") int minionSlots, + @SerializedName("guest_count") int guestCount, + @SerializedName("coop_slots") int coopSlots, + @SerializedName("coins_allowance") int coinsAllowance + ){} +} diff --git a/src/main/java/lel/flummi/skilloverlay/mixin/GameRenderMixin.java b/src/main/java/lel/flummi/skilloverlay/mixin/GameRenderMixin.java new file mode 100644 index 0000000..1c1a957 --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/mixin/GameRenderMixin.java @@ -0,0 +1,25 @@ +package lel.flummi.skilloverlay.mixin; + +import lel.flummi.skilloverlay.skilloverlay; +import net.minecraft.client.MinecraftClient; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Environment(EnvType.CLIENT) +@Mixin(InGameHud.class) +public abstract class GameRenderMixin { + @Shadow @Final private MinecraftClient client; + + @Inject(at = @At("RETURN"), method = "render") + private void render(MatrixStack matrices, float tickDelta, CallbackInfo ci) { + skilloverlay.OVERLAY.render(matrices, client); + } +} diff --git a/src/main/java/lel/flummi/skilloverlay/overlays/FarmingOverlay.java b/src/main/java/lel/flummi/skilloverlay/overlays/FarmingOverlay.java new file mode 100644 index 0000000..d117407 --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/overlays/FarmingOverlay.java @@ -0,0 +1,306 @@ +package lel.flummi.skilloverlay.overlays; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.Formatting; +import net.minecraft.client.gui.DrawableHelper; +import com.mojang.blaze3d.systems.RenderSystem; + +import lel.flummi.skilloverlay.skilloverlay; +import lel.flummi.skilloverlay.utils.LerpUtils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; + +@Environment(EnvType.CLIENT) +public class FarmingOverlay extends DrawableHelper { + private MinecraftClient client; + private MatrixStack matrixStack; + + private long lastUpdate = -1; + private final LinkedList counterQueue = new LinkedList<>(); + private int cultivatingTier = -1; + private String cultivatingTierAmount = "1"; + private long counter = -1; + private int cultivating = -1; + private int cultivatingLast = -1; + private float cropsPerSecondLast = 0; + private float cropsPerSecond = 0; + private ArrayList cropsOverLastXSeconds = new ArrayList<>(); + private String cropName; + + public FarmingOverlay() { + /*HudRenderCallback.EVENT.register((matrixStack, tickDelta) -> { + if(client.player == null) + return; + this.render(matrixStack, client); + });*/ + } + + public void render(MatrixStack matrixStack, MinecraftClient client) { + if (client.player == null) + return; + + this.matrixStack = matrixStack; + this.client = MinecraftClient.getInstance(); + + RenderSystem.enableBlend(); + this.renderOverlay(); + + this.client.getProfiler().pop(); + } + + public void renderOverlay() { + this.lastUpdate = System.currentTimeMillis(); + ItemStack heldItem = client.player.getMainHandStack(); + String internalName = ""; + this.counter = 0; + boolean holdingFarmItem = false; + this.cultivatingLast = cultivating; + this.cultivating = 0; + + //System.out.println(skilloverlay.PROFILE.data().skills().get("farming").level()); + + if (heldItem != null) { + NbtCompound tag = heldItem.getNbt(); + + if (tag != null && tag.contains("ExtraAttributes", 10)) { + NbtCompound ea = tag.getCompound("ExtraAttributes"); + internalName = ea.getString("id"); + + for (CropType crop : CropType.values()) { + if (internalName.startsWith(crop.toolName)) { + this.cropName = crop.item; + holdingFarmItem = true; + } + } + if(holdingFarmItem) { + if (ea.contains("mined_crops", 99)) { + this.counter = ea.getLong("mined_crops"); + cultivating = ea.getInt("farmed_cultivating"); + this.counterQueue.add(0, this.counter); + } else if (ea.contains("farmed_cultivating", 99)) { + this.counter = ea.getInt("farmed_cultivating"); + cultivating = ea.getInt("farmed_cultivating"); + this.counterQueue.add(0, this.counter); + } + } + else + holdingFarmItem = false; + } + + if (this.cultivating < 1000) { + this.cultivatingTier = 1; + this.cultivatingTierAmount = "1,000"; + } else if (this.cultivating < 5000) { + this.cultivatingTier = 2; + this.cultivatingTierAmount = "5,000"; + } else if (this.cultivating < 25000) { + this.cultivatingTier = 3; + this.cultivatingTierAmount = "25,000"; + } else if (this.cultivating < 100000) { + this.cultivatingTier = 4; + this.cultivatingTierAmount = "100,000"; + } else if (this.cultivating < 300000) { + this.cultivatingTier = 5; + this.cultivatingTierAmount = "300,000"; + } else if (this.cultivating < 1500000) { + this.cultivatingTier = 6; + this.cultivatingTierAmount = "1,500,000"; + } else if (this.cultivating < 5000000) { + this.cultivatingTier = 7; + this.cultivatingTierAmount = "5,000,000"; + } else if (this.cultivating < 20000000) { + this.cultivatingTier = 8; + this.cultivatingTierAmount = "20,000,000"; + } else if (this.cultivating < 100000000) { + this.cultivatingTier = 9; + this.cultivatingTierAmount = "100,000,000"; + } else if (this.cultivating > 100000000) { + this.cultivatingTier = 10; + this.cultivatingTierAmount = "Maxed"; + } + } + + while (this.counterQueue.size() >= 4) { + this.counterQueue.removeLast(); + } + + if (this.counterQueue.isEmpty()) { + this.cropsPerSecond = -1; + this.cropsPerSecondLast = 0; + } else { + this.cropsPerSecondLast = this.cropsPerSecond; + long last = this.counterQueue.getLast(); + long first = this.counterQueue.getFirst(); + while (this.cropsOverLastXSeconds.size() > 60) { + this.cropsOverLastXSeconds.remove(0); + } + if ((first - last) / 2f != 0) { + this.cropsOverLastXSeconds.add((first - last) / 2f); + } else { + if (this.cropsPerSecondLast == 0) { + int i = 12; + while (i > 0) { + i--; + if (this.cropsOverLastXSeconds.size() > 0) { + this.cropsOverLastXSeconds.remove(0); + } else { + break; + } + } + } + } + + if (!holdingFarmItem) { + this.cropsOverLastXSeconds.clear(); + this.cropsPerSecond = -1; + this.cropsPerSecondLast = 0; + } + + ArrayList temp = new ArrayList<>(cropsOverLastXSeconds); + if (this.cropsOverLastXSeconds.size() >= 3) { + temp.remove(Collections.min(temp)); + } + if (this.cropsOverLastXSeconds.size() >= 6) { + temp.remove(Collections.min(temp)); + temp.remove(Collections.max(temp)); + } + if (this.cropsOverLastXSeconds.size() >= 10) { + temp.remove(Collections.max(temp)); + } + + float cropsOverLastXSecondsTotal = 0; + for (Float crops : temp) { + cropsOverLastXSecondsTotal += crops; + } + this.cropsPerSecond = temp.size() != 0 && cropsOverLastXSecondsTotal != 0 + ? cropsOverLastXSecondsTotal / temp.size() + : 0; + } + + ArrayList overlayStringList = new ArrayList<>(); + NumberFormat format = NumberFormat.getIntegerInstance(); + + // Add all the lines to the array + if (this.counter >= 0 && this.cultivating != this.counter) { + overlayStringList.add(new OverlayString("Counter", format.format(this.counter))); + } + + if (this.counter >= 0) { + if (this.cropsPerSecondLast == this.cropsPerSecond && this.cropsPerSecond <= 0) { + overlayStringList.add(new OverlayString(this.cropName + "/m", "N/A")); + } else { + float cpsInterp = interp(this.cropsPerSecond, this.cropsPerSecondLast); + overlayStringList.add(new OverlayString(this.cropName + "/m", String.format("%,.2f", cpsInterp * 60 * 30))); + } + } + + if (this.cultivatingTier <= 9 && this.cultivating > 0) { + int counterInterp = (int) interp(this.cultivating, this.cultivatingLast); + overlayStringList.add(new OverlayString("Cultivating", format.format(counterInterp) + "/" + this.cultivatingTierAmount)); + } + if (this.cultivatingTier == 10) { + int counterInterp = (int) interp(this.cultivating, this.cultivatingLast); + overlayStringList.add(new OverlayString("Cultivating", format.format(counterInterp))); + } + + float yaw = client.player.getYaw(); + float pitch = client.player.getPitch(); + yaw %= 360; + if (yaw < 0) + yaw += 360; + if (yaw > 180) + yaw -= 360; + pitch %= 360; + if (pitch < 0) + pitch += 360; + if (pitch > 180) + pitch -= 360; + + overlayStringList.add(new OverlayString("Yaw", String.format("%.2f", yaw) + Formatting.BOLD + "\u1D52")); + overlayStringList.add(new OverlayString("Pitch", String.format("%.2f", pitch) + Formatting.BOLD + "\u1D52")); + + if (!holdingFarmItem) { + overlayStringList.clear(); + } + + // Draw HUD + int xAxis = 10; + int yAxis = 200; + + // Get the longest string in the array + int longestString = 0; + int BoxWidth = 0; + for (OverlayString s : overlayStringList) { + String combined = s.toString(); + if (combined.length() > longestString) { + longestString = combined.length(); + BoxWidth = this.client.textRenderer.getWidth(combined); + } + } + + int lineHeight = this.client.textRenderer.fontHeight + 2; + + DrawableHelper.fill(matrixStack, xAxis, yAxis, xAxis + BoxWidth + 10, + yAxis + ((lineHeight + 1) * overlayStringList.size()), 0x64000000); + + for (OverlayString line : overlayStringList) { + int offset = 5; + + this.client.textRenderer.drawWithShadow(this.matrixStack, line.toString(), xAxis + offset, yAxis + offset, 0xFFFFFF); + yAxis += lineHeight; + } + } + + private float interp(float now, float last) { + float interp = now; + if (last >= 0 && last != now) { + float factor = (System.currentTimeMillis() - this.lastUpdate) / 1000f; + factor = LerpUtils.clampZeroOne(factor); + interp = last + (now - last) * factor; + } + return interp; + } + + private enum CropType { + WHEAT("THEORETICAL_HOE_WHEAT", "Wheat"), + NETHER_WART("THEORETICAL_HOE_WARTS", "Warts"), + SUGAR_CANE("THEORETICAL_HOE_CANE", "Sugar"), + CARROT("THEORETICAL_HOE_CARROT", "Carrots"), + POTATO("THEORETICAL_HOE_POTATO", "Potatoes"), + COCOA_BEANS("COCO_CHOPPER", "Cocoas"), + PUMPKIN("PUMPKIN_DICER", "Pumpkins"), + MELON("MELON_DICER", "Melons"), + CACTUS("CACTUS_KNIFE", "Cactus"), + ; + + private final String toolName; + private final String item; + + CropType(String toolName, String item) { + this.toolName = toolName; + this.item = item; + } + } + + private class OverlayString { + final String type; + final String text; + + private OverlayString(String type, String text) { + this.type = type; + this.text = text; + } + + public String toString() { + return Formatting.AQUA + this.type + ": " + Formatting.YELLOW + this.text; + } + } +} diff --git a/src/main/java/lel/flummi/skilloverlay/overlays/FarmingOverlay.java.unused b/src/main/java/lel/flummi/skilloverlay/overlays/FarmingOverlay.java.unused new file mode 100644 index 0000000..4b8c87b --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/overlays/FarmingOverlay.java.unused @@ -0,0 +1,73 @@ +package lel.flummi.skilloverlay.overlays; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.gui.DrawableHelper; +import com.mojang.blaze3d.systems.RenderSystem; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import java.util.ArrayList; + +@Environment(EnvType.CLIENT) +public class FarmingOverlay extends DrawableHelper { + private MinecraftClient client; + private MatrixStack matrixStack; + + public FarmingOverlay() {} + + public void render(MatrixStack matrixStack, MinecraftClient client) { + this.matrixStack = matrixStack; + this.client = MinecraftClient.getInstance(); + + RenderSystem.enableBlend(); + this.renderOverlay(); + + this.client.getProfiler().pop(); + } + + public void renderOverlay() { + ArrayList overlayStringList = new ArrayList<>(); + + // Add all the lines to the array + overlayStringList.add("Test"); + + //Remove empty lines from the array + overlayStringList.removeIf(String::isEmpty); + + // Draw HUD + int Xcords = 10; + int Ycords = 200; + + // Get the longest string in the array + int longestString = 0; + int BoxWidth = 0; + for (String s : overlayStringList) { + if (s.length() > longestString) { + longestString = s.length(); + BoxWidth = this.client.textRenderer.getWidth(s); + } + } + + int lineHeight = this.client.textRenderer.fontHeight + 2; + int yAxis = (((this.client.getWindow().getScaledHeight()) - ((lineHeight + 4) * overlayStringList.size())) + (lineHeight + 4)) * (Ycords) / 100; + int xAxis = ((this.client.getWindow().getScaledWidth() - 4) - (BoxWidth)) * Xcords / 100; + + // Add Padding to left of the screen + if (xAxis <= 4) { + xAxis = 4; + } + + for (String line : overlayStringList) { + int offset = 0; + if (Xcords >= 50) { + int lineLength = this.client.textRenderer.getWidth(line); + offset = (BoxWidth - lineLength); + } + + this.client.textRenderer.drawWithShadow(this.matrixStack, line, xAxis + offset, yAxis + 4, 0xFFFFFF); + yAxis += lineHeight; + } + } +} diff --git a/src/main/java/lel/flummi/skilloverlay/skilloverlay.java b/src/main/java/lel/flummi/skilloverlay/skilloverlay.java new file mode 100644 index 0000000..a73af8e --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/skilloverlay.java @@ -0,0 +1,23 @@ +package lel.flummi.skilloverlay; + +import net.fabricmc.api.ModInitializer; + +import lel.flummi.skilloverlay.overlays.FarmingOverlay; + +import lel.flummi.skilloverlay.api.PlayerProfile; + +public class skilloverlay implements ModInitializer { + public static FarmingOverlay OVERLAY; + public static PlayerProfile API; + + @Override + public void onInitialize() { + System.out.println("Skilloverlay started."); + + OVERLAY = new FarmingOverlay(); + + PlayerProfile.init(); + + //System.out.println(profiles.profiles().get("b2255349-d395-4169-9980-3ec0a32b2cfb").data().skills().get("farming").xp()); + } +} diff --git a/src/main/java/lel/flummi/skilloverlay/utils/LerpUtils.java b/src/main/java/lel/flummi/skilloverlay/utils/LerpUtils.java new file mode 100644 index 0000000..4b04b5b --- /dev/null +++ b/src/main/java/lel/flummi/skilloverlay/utils/LerpUtils.java @@ -0,0 +1,24 @@ +package lel.flummi.skilloverlay.utils; + +public class LerpUtils { + public static float clampZeroOne(float f) { + return Math.max(0, Math.min(1, f)); + } + + public static float sigmoid(float val) { + return (float) (1 / (1 + Math.exp(-val))); + } + + private static final float sigmoidStr = 8; + private static final float sigmoidA = -1 / (sigmoid(-0.5f * sigmoidStr) - sigmoid(0.5f * sigmoidStr)); + private static final float sigmoidB = sigmoidA * sigmoid(-0.5f * sigmoidStr); + + public static float sigmoidZeroOne(float f) { + f = clampZeroOne(f); + return sigmoidA * sigmoid(sigmoidStr * (f - 0.5f)) - sigmoidB; + } + + public static float lerp(float a, float b, float amount) { + return b + (a - b) * clampZeroOne(amount); + } +} diff --git a/src/main/resources/assets/skilloverlay/icon.png b/src/main/resources/assets/skilloverlay/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..047b91f2347de5cf95f23284476fddbe21ba23fe GIT binary patch literal 453 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykgMrH;EhMylkcQ7z8um$*pxH2#>{Qv)d>CO3f z85kI=JY5_^JdR(zyfHV%kcTaSi%Ti|TJ8eTpj}+~BK-x@9*$y@%`bB3L~{I!eX+NC zlHNB-j&%mwkF+BM{`*I?$?=)ih{~Me5!39upp((GtLc_m^NimC=^Eh|csG&)*Qrd==Y&n7UmRi%(N^JM_;TeSC#QK=Zw9+^jOG>IE8SNYJSk~k z5Y{~5u4B_KzVpl#mXe%1nZx7v{xLh$%INe`pm#$_heN5*Wsb9+XN1@{9Ex1z(lBBD zfu+n0IR}_qbms6I2yJTN%V+rDUK=z&u7V-ReL3?h|HUpQ3^T2mq-JhoG}|zP;mL%$ z02u{`Lo>b};n%wGII;gbLmq2&gV6#PbAj{<#d(dv5emOqPjS5xTT#|n#+=r;uYW?G zg5HF1jT-(wi;N%QEGzc2Uws>3-(cqWm+OF@xgGO=#y@{$DjL3dZ1~U27a%9M#WB_~ ze1i4@=WpBrGaNhA7u@UT+|V$WVdeG@FLI@{%+7spEU!B``w&Z{=X?eR1_n=8KbLh* G2~7YM=(B48 literal 0 HcmV?d00001 diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..02e8dba --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,34 @@ +{ + "schemaVersion": 1, + "id": "skilloverlay", + "version": "${version}", + "name": "skilloverlay", + "description": "skilloverlay for Hypixel Skyblock", + "authors": [ + "Flummi" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + + "license": "GNU LGPLv3", + "icon": "assets/skilloverlay/icon.png", + + "environment": "client", + "entrypoints": { + "main": [ + "lel.flummi.skilloverlay.skilloverlay" + ] + }, + "mixins": [ + "skilloverlay.mixins.json" + ], + + "depends": { + "fabricloader": ">=0.14.19", + "fabric-api": ">=0.81.0+1.19.4", + "minecraft": "~1.19.4", + "java": ">=17" + } +} diff --git a/src/main/resources/skilloverlay.mixins.json b/src/main/resources/skilloverlay.mixins.json new file mode 100644 index 0000000..f9bff9b --- /dev/null +++ b/src/main/resources/skilloverlay.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "lel.flummi.skilloverlay.mixin", + "compatibilityLevel": "JAVA_17", + "client": [ + "GameRenderMixin" + ], + "injectors": { + "defaultRequire": 1 + } +}