aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MRREADME.md225
-rw-r--r--build.gradle16
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin62076 -> 63721 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties3
-rwxr-xr-xgradlew22
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java3
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/ConfigUtils.java14
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java67
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/categories/DungeonsCategory.java19
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/categories/GeneralCategory.java69
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownController.java25
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilder.java17
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilderImpl.java12
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/events/ClientPlayerBlockBreakEvent.java23
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/events/SkyblockEvents.java (renamed from src/main/java/me/xmrvizzy/skyblocker/utils/SkyblockEvents.java)2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java27
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/DrawContextMixin.java12
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java6
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java34
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfit.java2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/item/ItemCooldowns.java115
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/item/ItemRarityBackgrounds.java109
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/item/SkyblockItemRarity.java29
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ResultButtonWidget.java4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/ItemUtils.java14
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java1
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/discord/DiscordRPCManager.java12
-rw-r--r--src/main/resources/assets/skyblocker/lang/en_us.json7
-rw-r--r--src/main/resources/assets/skyblocker/textures/gui/sprites/item_rarity_background.pngbin0 -> 198 bytes
-rw-r--r--src/main/resources/skyblocker.mixins.json7
-rw-r--r--src/test/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfitTest.java20
32 files changed, 777 insertions, 141 deletions
diff --git a/MRREADME.md b/MRREADME.md
new file mode 100644
index 00000000..7e1e68ad
--- /dev/null
+++ b/MRREADME.md
@@ -0,0 +1,225 @@
+<img height="150" src="https://hysky.de/skyblocker.png" />
+
+## Skyblocker
+
+Hypixel Skyblock Mod for Minecraft 1.17.x + 1.18.x + 1.19.x + 1.20.x
+
+## 🔧 Configuration - [Mod Menu](https://modrinth.com/mod/modmenu) not required
+open config with modmenu \
+or **/skyblocker config**
+
+Skyblocker has a variety of configurations. \
+To access the configuration menu, you must install [Mod Menu](https://modrinth.com/mod/modmenu).
+<figure><a href="https://cdn-raw.modrinth.com/data/y6DuFGwJ/images/7a284adbbdc9cbad48c627e3898dc8cfb9f54a64.png"><img src="https://cdn.modrinth.com/data/y6DuFGwJ/images/7a284adbbdc9cbad48c627e3898dc8cfb9f54a64.png" alt="Mod Menu" style="width:100%"></a><figcaption align = "center"><b>Mod Menu - Skyblocker config</b></figcaption></figure>
+
+### List of Configuration
+
+<details>
+<summary> General </summary>
+
+|Config option|Description|
+|---|---|
+| Update Notification | Get notified when there is a new update |
+| View [backpack preview](https://cdn-raw.modrinth.com/data/y6DuFGwJ/images/ef33e34b79c1615bcb23f3a395b29b793ef32e34.png) without holding shift | Preview on hover |
+
+<details>
+<summary> Health, Mana, Defence & XP Bars </summary>
+
+|Config option|Description|
+|---|---|
+|Enable Bars| Change Minecraft health ui with skyblocker [custom ui](https://user-images.githubusercontent.com/27798256/170806938-f858f0ae-4d8b-4767-9b53-8fe5a65edf56.png)|
+|Configure Bar Position|[Customize Bar Positions](https://cdn.discordapp.com/attachments/1103292463558438993/1103292498345984070/healt-layer.png)|
+</details>
+
+<details>
+<summary> Item List </summary>
+
+|Config option|Description|
+|---|---|
+|Enable Item List| Acitvate [recipe viewer](https://cdn-raw.modrinth.com/data/y6DuFGwJ/images/cf9f8077067b9781686f23116f163d529c21c404.png)|
+</details>
+
+<details>
+<summary> Item Tooltip </summary>
+
+Customize [Item tooltip](https://cdn-raw.modrinth.com/data/y6DuFGwJ/images/12903f3f839d769fac48a4e74e04bee9aa1657d5.png)
+
+</details>
+
+<details>
+<summary> Hitboxes </summary>
+
+|Config option|Description|
+|---|---|
+|Enable 1.8 farmland hitbox| Change hitbox to the 1.8 one |
+|Enable 1.8 lever hitbox| Change hitbox to the 1.8 one |
+</details>
+</details>
+
+<details>
+<summary> Locations </summary>
+
+<details>
+<summary> Dungeons </summary>
+
+|Config option|Description|
+|---|---|
+|Croseus Helper|Gray out chests that have already been opened|
+|Enable Map| [Map](https://cdn-raw.modrinth.com/data/y6DuFGwJ/images/43243429b1c4d17236ae3e5a9836ecd7d905644b.png)|
+|Solve Three Weirdos Puzzle|Solver usefull in Dungeons|
+|Solve Blaze Puzzle|Solver usefull in Dungeons|
+|Solve Trivia Puzzle|Solver usefull in Dungeons|
+
+<details>
+<summary> Terminal </summary>
+
+|Config option|Description|
+|---|---|
+|Solve Selectect Colored|Solver usefull in Dungeons 7|
+|Solve Click In Order|Solver usefull in Dungeons 7|
+|Solve Starts With|Solver usefull in Dungeons 7|
+</details>
+</details>
+<details>
+<summary> Dwarven Mines </summary>
+
+|Config option|Description|
+|---|---|
+|Enable Drill Fuel|[Drill icon](https://cdn-raw.modrinth.com/data/y6DuFGwJ/images/43c7ab7aa7c90fcf833c7cddbf73e6644c6ce5fa.png)|
+|Solve Fetchur| Solver usefull in Mines|
+|Solve Puzzler Puzzle| Solver usefull in Mines |
+|Dwarven Hud| [Commision Hud](https://cdn.discordapp.com/attachments/905867886428565565/950513333478494248/Screen_Shot_2022-03-07_at_4.58.12_PM.png)|
+</details>
+</details>
+
+
+<details>
+<summary> Quick Navigation </summary>
+
+|Config option|Description|
+|---|---|
+|Enable Quick Navigation|Enable [Quicknav](https://cdn.discordapp.com/attachments/1103292463558438993/1103358576870817866/quick-nav.png)|
+<details>
+<summary> Button 1-12 </summary>
+
+|Config option|Description|
+|---|---|
+|Render|To show the tab|
+|Item name| The name of the item e.g. iron_boots |
+|NBT| NBT tag of the item e.g. custom head id on skull item|
+|UI Title| Title of the tab|
+|Click event|The command that is executed when you click the tab|
+</details>
+</details>
+
+
+<details>
+<summary> Messages </summary>
+
+|Config option|Description|
+|---|---|
+|Hide Ability Cooldown|Disable,Filter or Move to action bar|
+|Hide Heal Messages|Disable,Filter or Move to action bar|
+|Hide AOTE Messages|Disable,Filter or Move to action bar|
+|Hide Implosion Message|Disable,Filter or Move to action bar|
+|Hide Molten Wave Message|Disable,Filter or Move to action bar|
+|Hide Ads from Public Chat|Disable,Filter or Move to action bar|
+|Hide Teleport Pad Messages|Disable,Filter or Move to action bar|
+|Hide Combo Messages|Disable,Filter or Move to action bar|
+|Hide Autopet Messages|Disable,Filter or Move to action bar|
+|Hide Mana Consumption Messages from Action Bar|Activate or deactivate|
+</details>
+
+
+<details>
+<summary> Discord Rich Presence </summary>
+
+|Config option|Description|
+|---|---|
+|Enable|Activate [Discord Rich Presence](https://cdn-raw.modrinth.com/data/y6DuFGwJ/images/f6314d0ae0fc24d77fb3371e59b7abfe4774a17e.png)|
+|Skyblock Info|Choose between Location,Purse and Bits|
+|Cycle Skyblock Info| Cycles between the three options|
+|Custom Message| Show a custom message|
+</details>
+
+## 🖼️ Images
+Click [#Gallery](https://modrinth.com/mod/skyblocker-liap/gallery) for images to this mod
+
+## 📖Features
+<details open>
+<summary>open</summary>
+
+* Bars: Health and absorption, Mana, Defense, XP (moving fancy bars)
+* Hide Messages: Ability Cooldown, Heal, AOTE, Implosion, Molten Wave, Teleport Pad Messages
+* Dungeon Minimap
+* Dungeon Secrets
+* Starred Mob Glow
+* Dungeon Puzzle Solver:
+ * Three Weirdos
+ * Blaze
+ * Tic Tac Toe
+ * Croesus
+ * Terminal:
+ * Order
+ * Coloured Items
+ * Item Name
+* Dwarven Mines Solver: Fetchur, Puzzler
+* Barn Solver: Treasure Hunter, Hungry Hiker
+* Experiments Solvers
+* Slayer helper:
+ * Vampire : Effigy Waypoints, Healing Melon Indicator, Twinclaws Ice Indicator, Steak Stake Indicator
+* Drill Fuel and Pickonimbus 2000 in Item Durability Bar
+* Hotbar Slot Lock Keybind (Select the hotbar slot you want to lock/unlock and press the lockbutton)
+* Price tooltip: npc, motes, bazaar (avg, lbin), ah, museum
+* reparty: write /rp to reparty + auto rejoin
+* Wiki Lookup: press f4 to open the wiki page about the held item
+* Discord Rich Presence: Allows user to show either their Piggy, Bits, or location. Along with a custom message
+* Quicknav: fast navigate between pets, armor, enderchest, skill, collection, crafting, enchant, envil, warp dungeon,
+ warp hub
+* Recipe book: in the vanilla recipe book all skyblock items are listed, and you can see the recipe of the item
+* Backpack preview: after you clicked your backpack or enderchest once you can hover over the backpack or enderchest and
+ hold shift to preview
+* Update notification
+* Commission HUD: Dwarven Mines quests
+* 1.8 hitbox for lever and farmland
+* Custom Tab HUD + Fully configureable with ressourcepack
+* Roughly enough items (REI) and Emi Support
+* Fishing Helper + sound notification
+* Mirrorverse Waypoints
+* Attribute Shard Info Display
+* Item and Armour customisation:
+ * Item Renaming
+ * Custom Armour Dye Colours
+ * Custom Armour Trims
+* OptiFabric Compatibility
+* Rare Drop Special Effects! Dungeon chest
+* Dungeon Chest Profit Calculator
+* Hide Status Effect Overlay
+* Personal Compactor/Deletor preview
+* Hide fake players in social interactions screen
+* hidden relic helper
+
+</details>
+
+
+## [Modpack](https://modrinth.com/modpack/skyblocker-modpack)
+
+<details open>
+<summary>open</summary>
+
+1. [Here](https://docs.modrinth.com/docs/modpacks/playing_modpacks) is a tutorial how to install it easy with a launcher.
+2. Download the [Skyblocker Modpack](https://modrinth.com/modpack/skyblocker-modpack/version/latest).
+ * Drag and drop the .mrpack file into a Custom MC Launcher like [MultiMC](https://multimc.org/) or [Prism Launcher](https://prismlauncher.org/) and start the new instance.
+
+</details>
+
+## Kinetic Hosting Affiliate - 15% off your first month
+
+Looking for an affordable and reliable hosting platform for your Minecraft server? Look no further than Kinetic Hosting! As an affiliate partner with Kinetic Hosting, we highly recommend their service. They offer fast and reliable servers with the largest range of supported modpacks.
+
+As a special offer for our audience, you can **<u>[use the discount code "Skyblocker" during checkout to get 15% off your first month](https://billing.kinetichosting.net/aff.php?aff=315)</u>**.
+This helps to cover our server costs.
+
+[![Kinetic-hosting](https://cdn.discordapp.com/attachments/1098004599757099150/1099460202924879902/Skyblocker.png)](https://billing.kinetichosting.net/aff.php?aff=315)
+
+So what are you waiting for? Click on the **<u>[link](https://billing.kinetichosting.net/aff.php?aff=315)</u>** to check out Kinetic Hosting and start playing with your friends today! \ No newline at end of file
diff --git a/build.gradle b/build.gradle
index d26c0e92..3e4a13d3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
plugins {
- id 'fabric-loom' version '1.3-SNAPSHOT'
+ id 'fabric-loom' version '1.4-SNAPSHOT'
id 'maven-publish'
id 'com.modrinth.minotaur' version '2.+'
}
@@ -140,18 +140,22 @@ modrinth {
gameVersions = [project.minecraft_version]
loaders = ["fabric"]
versionType = "release"
- dependencies = [ // Yet another array. Create a new `ModDependency` or `VersionDependency` with two strings - the ID and the scope
- new ModDependency("P7dR8mSH", "required"), // Creates a new required dependency on Fabric API
- new ModDependency("mOgUt4GM", "optional"), // modmenu
- new ModDependency("nfn13YXA", "optional") // REI
- ]
+ dependencies {
+ required.project "fabric-api"
+ optional.project "modmenu"
+ optional.project "rei"
+ optional.project "emi"
+ }
changelog = System.getenv('CHANGELOG')
+ syncBodyFrom = rootProject.file("MRREADME.md").text
}
tasks.modrinth.doLast {
println "::set-output name=url::https://modrinth.com/mod/skyblocker-liap/version/$uploadInfo.id"
}
+tasks.modrinth.dependsOn(tasks.modrinthSyncBody)
+
// configure the maven publication
publishing {
publications {
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index c1962a79..7f93135c 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 37aef8d3..3fa8f862 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index aeb74cbb..1aa94a42 100755
--- a/gradlew
+++ b/gradlew
@@ -83,7 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -130,10 +131,13 @@ location of your Java installation."
fi
else
JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
@@ -141,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -149,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -198,11 +202,11 @@ 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.
+# 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" \
diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
index 07a5be76..6f4276e9 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
@@ -4,6 +4,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import me.xmrvizzy.skyblocker.config.SkyblockerConfigManager;
import me.xmrvizzy.skyblocker.skyblock.*;
+import me.xmrvizzy.skyblocker.skyblock.item.ItemCooldowns;
import me.xmrvizzy.skyblocker.skyblock.dungeon.*;
import me.xmrvizzy.skyblocker.skyblock.dungeon.secrets.DungeonSecrets;
import me.xmrvizzy.skyblocker.skyblock.dwarven.DwarvenHud;
@@ -78,6 +79,7 @@ public class SkyblockerMod implements ClientModInitializer {
Relics.init();
BackpackPreview.init();
QuickNav.init();
+ ItemCooldowns.init();
DwarvenHud.init();
ChatMessageListener.init();
Shortcuts.init();
@@ -101,6 +103,7 @@ public class SkyblockerMod implements ClientModInitializer {
QuiverWarning.init();
SpecialEffects.init();
ItemProtection.init();
+ ItemRarityBackgrounds.init();
containerSolverManager.init();
statusBarTracker.init();
Scheduler.INSTANCE.scheduleCyclic(Utils::update, 20);
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/ConfigUtils.java b/src/main/java/me/xmrvizzy/skyblocker/config/ConfigUtils.java
index 28ed704b..552ed091 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/ConfigUtils.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/ConfigUtils.java
@@ -3,9 +3,17 @@ package me.xmrvizzy.skyblocker.config;
import dev.isxander.yacl3.api.Option;
import dev.isxander.yacl3.api.controller.BooleanControllerBuilder;
import dev.isxander.yacl3.api.controller.EnumControllerBuilder;
-import me.xmrvizzy.skyblocker.config.controllers.EnumDropdownControllerBuilder;
+import dev.isxander.yacl3.api.controller.ValueFormatter;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.function.Function;
public class ConfigUtils {
+ public static final Function<Formatting, String> FORMATTING_TO_STRING = formatting -> StringUtils.capitalize(formatting.getName().replaceAll("_", " "));
+ public static final ValueFormatter<Float> FLOAT_TWO_FORMATTER = value -> Text.literal(String.format("%,.2f", value).replaceAll("[\u00a0\u202F]", " "));
+
public static BooleanControllerBuilder createBooleanController(Option<Boolean> opt) {
return BooleanControllerBuilder.create(opt).yesNoFormatter().coloured(true);
}
@@ -14,8 +22,4 @@ public class ConfigUtils {
public static <E extends Enum<E>> EnumControllerBuilder<E> createEnumCyclingListController(Option<E> opt) {
return EnumControllerBuilder.create(opt).enumClass((Class<E>) opt.binding().defaultValue().getClass());
}
-
- public static <E extends Enum<E>> EnumDropdownControllerBuilder<E> createEnumDropdownController(Option<E> opt) {
- return EnumDropdownControllerBuilder.create(opt);
- }
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
index e40c3f21..8e014124 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
@@ -1,10 +1,5 @@
package me.xmrvizzy.skyblocker.config;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-
import dev.isxander.yacl3.config.v2.api.SerialEntry;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
@@ -15,6 +10,9 @@ import net.minecraft.client.resource.language.I18n;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
+import java.util.ArrayList;
+import java.util.List;
+
public class SkyblockerConfig {
@SerialEntry
public int version = 1;
@@ -179,6 +177,9 @@ public class SkyblockerConfig {
public FairySouls fairySouls = new FairySouls();
@SerialEntry
+ public ItemCooldown itemCooldown = new ItemCooldown();
+
+ @SerialEntry
public Shortcuts shortcuts = new Shortcuts();
@SerialEntry
@@ -315,6 +316,11 @@ public class SkyblockerConfig {
public boolean highlightOnlyNearbySouls = false;
}
+ public static class ItemCooldown {
+ @SerialEntry
+ public boolean enableItemCooldowns = true;
+ }
+
public static class Shortcuts {
@SerialEntry
public boolean enableShortcuts = true;
@@ -461,6 +467,12 @@ public class SkyblockerConfig {
public static class ItemInfoDisplay {
@SerialEntry
public boolean attributeShardInfo = true;
+
+ @SerialEntry
+ public boolean itemRarityBackgrounds = false;
+
+ @SerialEntry
+ public float itemRarityBackgroundsOpacity = 1f;
}
public static class SpecialEffects {
@@ -581,55 +593,18 @@ public class SkyblockerConfig {
public int neutralThreshold = 1000;
@SerialEntry
- public FormattingOption neutralColor = FormattingOption.DARK_GRAY;
+ public Formatting neutralColor = Formatting.DARK_GRAY;
@SerialEntry
- public FormattingOption profitColor = FormattingOption.DARK_GREEN;
+ public Formatting profitColor = Formatting.DARK_GREEN;
@SerialEntry
- public FormattingOption lossColor = FormattingOption.RED;
+ public Formatting lossColor = Formatting.RED;
@SerialEntry
- public FormattingOption incompleteColor = FormattingOption.BLUE;
+ public Formatting incompleteColor = Formatting.BLUE;
}
-
- public enum FormattingOption {
- BLACK(Formatting.BLACK),
- DARK_BLUE(Formatting.DARK_BLUE),
- DARK_GREEN(Formatting.DARK_GREEN),
- DARK_AQUA(Formatting.DARK_AQUA),
- DARK_RED(Formatting.DARK_RED),
- DARK_PURPLE(Formatting.DARK_PURPLE),
- GOLD(Formatting.GOLD),
- GRAY(Formatting.GRAY),
- DARK_GRAY(Formatting.DARK_GRAY),
- BLUE(Formatting.BLUE),
- GREEN(Formatting.GREEN),
- AQUA(Formatting.AQUA),
- RED(Formatting.RED),
- LIGHT_PURPLE(Formatting.LIGHT_PURPLE),
- YELLOW(Formatting.YELLOW),
- WHITE(Formatting.WHITE),
- OBFUSCATED(Formatting.OBFUSCATED),
- BOLD(Formatting.BOLD),
- STRIKETHROUGH(Formatting.STRIKETHROUGH),
- UNDERLINE(Formatting.UNDERLINE),
- ITALIC(Formatting.ITALIC),
- RESET(Formatting.RESET);
-
- public final Formatting formatting;
-
-
- FormattingOption(Formatting formatting) {
- this.formatting = formatting;
- }
-
- @Override
- public String toString() {
- return StringUtils.capitalize(formatting.getName().replaceAll("_", " "));
- }
- }
public static class LividColor {
@SerialEntry
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/categories/DungeonsCategory.java b/src/main/java/me/xmrvizzy/skyblocker/config/categories/DungeonsCategory.java
index 16439cb5..2d641ac1 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/categories/DungeonsCategory.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/categories/DungeonsCategory.java
@@ -10,11 +10,12 @@ import dev.isxander.yacl3.api.controller.FloatFieldControllerBuilder;
import dev.isxander.yacl3.api.controller.IntegerFieldControllerBuilder;
import dev.isxander.yacl3.api.controller.StringControllerBuilder;
import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
-import me.xmrvizzy.skyblocker.config.SkyblockerConfig.FormattingOption;
import me.xmrvizzy.skyblocker.config.ConfigUtils;
+import me.xmrvizzy.skyblocker.config.controllers.EnumDropdownControllerBuilder;
import me.xmrvizzy.skyblocker.skyblock.dungeon.DungeonMapConfigScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
public class DungeonsCategory {
@@ -150,34 +151,34 @@ public class DungeonsCategory {
newValue -> config.locations.dungeons.dungeonChestProfit.neutralThreshold = newValue)
.controller(IntegerFieldControllerBuilder::create)
.build())
- .option(Option.<FormattingOption>createBuilder()
+ .option(Option.<Formatting>createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.neutralColor"))
.binding(defaults.locations.dungeons.dungeonChestProfit.neutralColor,
() -> config.locations.dungeons.dungeonChestProfit.neutralColor,
newValue -> config.locations.dungeons.dungeonChestProfit.neutralColor = newValue)
- .controller(ConfigUtils::createEnumDropdownController)
+ .controller(EnumDropdownControllerBuilder.getFactory(ConfigUtils.FORMATTING_TO_STRING))
.build())
- .option(Option.<FormattingOption>createBuilder()
+ .option(Option.<Formatting>createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.profitColor"))
.binding(defaults.locations.dungeons.dungeonChestProfit.profitColor,
() -> config.locations.dungeons.dungeonChestProfit.profitColor,
newValue -> config.locations.dungeons.dungeonChestProfit.profitColor = newValue)
- .controller(ConfigUtils::createEnumDropdownController)
+ .controller(EnumDropdownControllerBuilder.getFactory(ConfigUtils.FORMATTING_TO_STRING))
.build())
- .option(Option.<FormattingOption>createBuilder()
+ .option(Option.<Formatting>createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.lossColor"))
.binding(defaults.locations.dungeons.dungeonChestProfit.lossColor,
() -> config.locations.dungeons.dungeonChestProfit.lossColor,
newValue -> config.locations.dungeons.dungeonChestProfit.lossColor = newValue)
- .controller(ConfigUtils::createEnumDropdownController)
+ .controller(EnumDropdownControllerBuilder.getFactory(ConfigUtils.FORMATTING_TO_STRING))
.build())
- .option(Option.<FormattingOption>createBuilder()
+ .option(Option.<Formatting>createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.incompleteColor"))
.description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.incompleteColor.@Tooltip")))
.binding(defaults.locations.dungeons.dungeonChestProfit.incompleteColor,
() -> config.locations.dungeons.dungeonChestProfit.incompleteColor,
newValue -> config.locations.dungeons.dungeonChestProfit.incompleteColor = newValue)
- .controller(ConfigUtils::createEnumDropdownController)
+ .controller(EnumDropdownControllerBuilder.getFactory(ConfigUtils.FORMATTING_TO_STRING))
.build())
.build())
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/categories/GeneralCategory.java b/src/main/java/me/xmrvizzy/skyblocker/config/categories/GeneralCategory.java
index c5e2d34c..318d579c 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/categories/GeneralCategory.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/categories/GeneralCategory.java
@@ -1,15 +1,12 @@
package me.xmrvizzy.skyblocker.config.categories;
-import dev.isxander.yacl3.api.ButtonOption;
-import dev.isxander.yacl3.api.ConfigCategory;
-import dev.isxander.yacl3.api.Option;
-import dev.isxander.yacl3.api.OptionDescription;
-import dev.isxander.yacl3.api.OptionGroup;
+import dev.isxander.yacl3.api.*;
import dev.isxander.yacl3.api.controller.FloatFieldControllerBuilder;
+import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder;
import dev.isxander.yacl3.api.controller.IntegerFieldControllerBuilder;
import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder;
-import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
import me.xmrvizzy.skyblocker.config.ConfigUtils;
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
import me.xmrvizzy.skyblocker.skyblock.shortcut.ShortcutsConfigScreen;
import me.xmrvizzy.skyblocker.utils.render.title.TitleContainerConfigScreen;
import net.minecraft.client.MinecraftClient;
@@ -17,10 +14,10 @@ import net.minecraft.text.Text;
public class GeneralCategory {
- public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig config) {
+ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig config) {
return ConfigCategory.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.category.general"))
-
+
//Ungrouped Options
.option(Option.<Boolean>createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.acceptReparty"))
@@ -57,7 +54,7 @@ public class GeneralCategory {
newValue -> config.general.hideStatusEffectOverlay = newValue)
.controller(ConfigUtils::createBooleanController)
.build())
-
+
//Tab Hud
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.tabHud"))
@@ -94,7 +91,7 @@ public class GeneralCategory {
.controller(ConfigUtils::createEnumCyclingListController)
.build())
.build())
-
+
//Fancy Bars
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.bars"))
@@ -135,7 +132,7 @@ public class GeneralCategory {
.controller(ConfigUtils::createEnumCyclingListController)
.build())
.build())
-
+
//Experiments Solver
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.experiments"))
@@ -162,7 +159,7 @@ public class GeneralCategory {
.controller(ConfigUtils::createBooleanController)
.build())
.build())
-
+
//Fishing Helper
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.fishing"))
@@ -175,7 +172,7 @@ public class GeneralCategory {
.controller(ConfigUtils::createBooleanController)
.build())
.build())
-
+
//Fairy Souls Helper
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.fairySouls"))
@@ -203,7 +200,20 @@ public class GeneralCategory {
.controller(ConfigUtils::createBooleanController)
.build())
.build())
-
+
+ //Item Cooldown
+ .group(OptionGroup.createBuilder()
+ .name(Text.translatable("text.autoconfig.skyblocker.option.general.itemCooldown"))
+ .collapsed(true)
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("text.autoconfig.skyblocker.option.general.itemCooldown.enableItemCooldowns"))
+ .binding(defaults.general.itemCooldown.enableItemCooldowns,
+ () -> config.general.itemCooldown.enableItemCooldowns,
+ newValue -> config.general.itemCooldown.enableItemCooldowns = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
+ .build())
+
//Shortcuts
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.shortcuts"))
@@ -238,7 +248,7 @@ public class GeneralCategory {
.action((screen, opt) -> MinecraftClient.getInstance().setScreen(new ShortcutsConfigScreen(screen)))
.build())
.build())
-
+
//Quiver Warning
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.quiverWarning"))
@@ -265,7 +275,7 @@ public class GeneralCategory {
.controller(ConfigUtils::createBooleanController)
.build())
.build())
-
+
//Item List
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.itemList"))
@@ -278,7 +288,7 @@ public class GeneralCategory {
.controller(ConfigUtils::createBooleanController)
.build())
.build())
-
+
//Item Tooltip
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.itemTooltip"))
@@ -335,7 +345,7 @@ public class GeneralCategory {
.controller(ConfigUtils::createBooleanController)
.build())
.build())
-
+
//Item Info Display
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.itemInfoDisplay"))
@@ -348,8 +358,23 @@ public class GeneralCategory {
newValue -> config.general.itemInfoDisplay.attributeShardInfo = newValue)
.controller(ConfigUtils::createBooleanController)
.build())
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgrounds"))
+ .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgrounds.@Tooltip")))
+ .binding(defaults.general.itemInfoDisplay.itemRarityBackgrounds,
+ () -> config.general.itemInfoDisplay.itemRarityBackgrounds,
+ newValue -> config.general.itemInfoDisplay.itemRarityBackgrounds = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
+ .option(Option.<Float>createBuilder()
+ .name(Text.translatable("text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgroundsOpacity"))
+ .binding(defaults.general.itemInfoDisplay.itemRarityBackgroundsOpacity,
+ () -> config.general.itemInfoDisplay.itemRarityBackgroundsOpacity,
+ newValue -> config.general.itemInfoDisplay.itemRarityBackgroundsOpacity = newValue)
+ .controller(opt -> FloatSliderControllerBuilder.create(opt).range(0f, 1f).step(0.05f).formatValue(ConfigUtils.FLOAT_TWO_FORMATTER))
+ .build())
.build())
-
+
//Special Effects
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.specialEffects"))
@@ -363,7 +388,7 @@ public class GeneralCategory {
.controller(ConfigUtils::createBooleanController)
.build())
.build())
-
+
//Hitboxes
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.hitbox"))
@@ -383,7 +408,7 @@ public class GeneralCategory {
.controller(ConfigUtils::createBooleanController)
.build())
.build())
-
+
//Title Container
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.titleContainer"))
@@ -430,7 +455,7 @@ public class GeneralCategory {
.action((screen, opt) -> MinecraftClient.getInstance().setScreen(new TitleContainerConfigScreen(screen)))
.build())
.build())
-
+
//Teleport Overlays
.group(OptionGroup.createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.general.teleportOverlay"))
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownController.java b/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownController.java
index cf40c7d5..6db0028c 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownController.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownController.java
@@ -8,16 +8,23 @@ import dev.isxander.yacl3.gui.controllers.dropdown.AbstractDropdownController;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
+import java.util.function.Function;
import java.util.stream.Stream;
public class EnumDropdownController<E extends Enum<E>> extends AbstractDropdownController<E> {
- protected EnumDropdownController(Option<E> option) {
+ /**
+ * The function used to convert enum constants to strings used for display, suggestion, and validation. Defaults to {@link Enum#toString}.
+ */
+ protected final Function<E, String> toString;
+
+ protected EnumDropdownController(Option<E> option, Function<E, String> toString) {
super(option);
+ this.toString = toString;
}
@Override
public String getString() {
- return option().pendingValue().toString();
+ return toString.apply(option().pendingValue());
}
@Override
@@ -26,15 +33,15 @@ public class EnumDropdownController<E extends Enum<E>> extends AbstractDropdownC
}
/**
- * Searches through enum constants for one whose {@link Enum#toString()} result equals {@code value}
+ * Searches through enum constants for one whose {@link #toString} result equals {@code value}
*
* @return The enum constant associated with the {@code value} or the pending value if none are found
- * @implNote The return value of {@link Enum#toString()} on each enum constant should be unique in order to ensure accuracy
+ * @implNote The return value of {@link #toString} on each enum constant should be unique in order to ensure accuracy
*/
private E getEnumFromString(String value) {
value = value.toLowerCase();
for (E constant : option().pendingValue().getDeclaringClass().getEnumConstants()) {
- if (constant.toString().toLowerCase().equals(value)) return constant;
+ if (toString.apply(constant).toLowerCase().equals(value)) return constant;
}
return option().pendingValue();
@@ -44,7 +51,7 @@ public class EnumDropdownController<E extends Enum<E>> extends AbstractDropdownC
public boolean isValueValid(String value) {
value = value.toLowerCase();
for (E constant : option().pendingValue().getDeclaringClass().getEnumConstants()) {
- if (constant.toString().equals(value)) return true;
+ if (toString.apply(constant).equals(value)) return true;
}
return false;
@@ -59,16 +66,16 @@ public class EnumDropdownController<E extends Enum<E>> extends AbstractDropdownC
}
/**
- * Filters and sorts through enum constants for those whose {@link Enum#toString()} result equals {@code value}
+ * Filters and sorts through enum constants for those whose {@link #toString} result equals {@code value}
*
* @return a sorted stream containing enum constants associated with the {@code value}
- * @implNote The return value of {@link Enum#toString()} on each enum constant should be unique in order to ensure accuracy
+ * @implNote The return value of {@link #toString} on each enum constant should be unique in order to ensure accuracy
*/
@NotNull
protected Stream<String> getValidEnumConstants(String value) {
String valueLowerCase = value.toLowerCase();
return Arrays.stream(option().pendingValue().getDeclaringClass().getEnumConstants())
- .map(Enum::toString)
+ .map(this.toString)
.filter(constant -> constant.toLowerCase().contains(valueLowerCase))
.sorted((s1, s2) -> {
String s1LowerCase = s1.toLowerCase();
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilder.java b/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilder.java
index baadb8b3..a17f58d6 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilder.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilder.java
@@ -3,8 +3,25 @@ package me.xmrvizzy.skyblocker.config.controllers;
import dev.isxander.yacl3.api.Option;
import dev.isxander.yacl3.api.controller.ControllerBuilder;
+import java.util.function.Function;
+
public interface EnumDropdownControllerBuilder<E extends Enum<E>> extends ControllerBuilder<E> {
+ EnumDropdownControllerBuilder<E> toString(Function<E, String> toString);
+
static <E extends Enum<E>> EnumDropdownControllerBuilder<E> create(Option<E> option) {
return new EnumDropdownControllerBuilderImpl<>(option);
}
+
+ /**
+ * Creates a factory for {@link EnumDropdownControllerBuilder}s with the given function for converting enum constants to strings.
+ * Use this if a custom toString function for an enum is needed.
+ * Use it like this:
+ * <pre>{@code Option.<MyEnum>createBuilder().controller(createEnumDropdownControllerBuilder.getFactory(MY_CUSTOM_ENUM_TO_STRING_FUNCTION))}</pre>
+ * @param toString The function used to convert enum constants to strings used for display, suggestion, and validation
+ * @return a factory for {@link EnumDropdownControllerBuilder}s
+ * @param <E> the enum type
+ */
+ static <E extends Enum<E>> Function<Option<E>, ControllerBuilder<E>> getFactory(Function<E, String> toString) {
+ return opt -> EnumDropdownControllerBuilder.create(opt).toString(toString);
+ }
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilderImpl.java b/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilderImpl.java
index ea30d1da..27878c86 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilderImpl.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/controllers/EnumDropdownControllerBuilderImpl.java
@@ -4,14 +4,24 @@ import dev.isxander.yacl3.api.Controller;
import dev.isxander.yacl3.api.Option;
import dev.isxander.yacl3.impl.controller.AbstractControllerBuilderImpl;
+import java.util.function.Function;
+
public class EnumDropdownControllerBuilderImpl<E extends Enum<E>> extends AbstractControllerBuilderImpl<E> implements EnumDropdownControllerBuilder<E> {
+ private Function<E, String> toString = Enum::toString;
+
public EnumDropdownControllerBuilderImpl(Option<E> option) {
super(option);
}
+ @Override
+ public EnumDropdownControllerBuilder<E> toString(Function<E, String> toString) {
+ this.toString = toString;
+ return this;
+ }
+
@SuppressWarnings("UnstableApiUsage")
@Override
public Controller<E> build() {
- return new EnumDropdownController<>(option);
+ return new EnumDropdownController<>(option, toString);
}
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/events/ClientPlayerBlockBreakEvent.java b/src/main/java/me/xmrvizzy/skyblocker/events/ClientPlayerBlockBreakEvent.java
new file mode 100644
index 00000000..76298612
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/events/ClientPlayerBlockBreakEvent.java
@@ -0,0 +1,23 @@
+package me.xmrvizzy.skyblocker.events;
+
+import net.fabricmc.fabric.api.event.Event;
+import net.fabricmc.fabric.api.event.EventFactory;
+import net.minecraft.block.BlockState;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+
+// Fabric API currently doesn't have an event for this
+public class ClientPlayerBlockBreakEvent {
+ public static final Event<AfterBlockBreak> AFTER = EventFactory.createArrayBacked(AfterBlockBreak.class,
+ (listeners) -> (world, player, pos, state) -> {
+ for (AfterBlockBreak listener : listeners) {
+ listener.afterBlockBreak(world, player, pos, state);
+ }
+ });
+
+ @FunctionalInterface
+ public interface AfterBlockBreak {
+ void afterBlockBreak(World world, PlayerEntity player, BlockPos pos, BlockState state);
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/SkyblockEvents.java b/src/main/java/me/xmrvizzy/skyblocker/events/SkyblockEvents.java
index 2dd83ffa..477d68b0 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/SkyblockEvents.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/events/SkyblockEvents.java
@@ -1,4 +1,4 @@
-package me.xmrvizzy.skyblocker.utils;
+package me.xmrvizzy.skyblocker.events;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java
new file mode 100644
index 00000000..3963f9d3
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java
@@ -0,0 +1,27 @@
+package me.xmrvizzy.skyblocker.mixin;
+
+import me.xmrvizzy.skyblocker.events.ClientPlayerBlockBreakEvent;
+import net.minecraft.block.BlockState;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.ClientPlayerInteractionManager;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
+
+@Mixin(ClientPlayerInteractionManager.class)
+public class ClientPlayerInteractionManagerMixin {
+ @Shadow
+ @Final
+ private MinecraftClient client;
+
+ @Inject(method = "breakBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;onBroken(Lnet/minecraft/world/WorldAccess;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)V"), locals = LocalCapture.CAPTURE_FAILHARD)
+ private void skyblocker$onBlockBroken(BlockPos pos, CallbackInfoReturnable<Boolean> cir, World world, BlockState blockState) {
+ ClientPlayerBlockBreakEvent.AFTER.invoker().afterBlockBreak(world, this.client.player, pos, blockState);
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/DrawContextMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/DrawContextMixin.java
index 2cb83e87..257a5127 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/mixin/DrawContextMixin.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/DrawContextMixin.java
@@ -1,12 +1,13 @@
package me.xmrvizzy.skyblocker.mixin;
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
-
import dev.cbyrne.betterinject.annotations.Arg;
import dev.cbyrne.betterinject.annotations.Inject;
import me.xmrvizzy.skyblocker.config.SkyblockerConfigManager;
import me.xmrvizzy.skyblocker.skyblock.item.AttributeShards;
+import me.xmrvizzy.skyblocker.skyblock.item.ItemCooldowns;
import me.xmrvizzy.skyblocker.utils.ItemUtils;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.minecraft.client.font.TextRenderer;
@@ -15,7 +16,6 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.Formatting;
-
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -64,4 +64,10 @@ public abstract class DrawContextMixin {
}
}
}
-} \ No newline at end of file
+
+ @ModifyExpressionValue(method = "drawItemInSlot(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/ItemCooldownManager;getCooldownProgress(Lnet/minecraft/item/Item;F)F"))
+ private float skyblocker$modifyItemCooldown(float cooldownProgress, @Local ItemStack stack) {
+ return Utils.isOnSkyblock() && ItemCooldowns.isOnCooldown(stack) ? ItemCooldowns.getItemCooldownEntry(stack).getRemainingCooldownPercent() : cooldownProgress;
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java
index 9ba2107b..7e94d660 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java
@@ -9,6 +9,7 @@ import me.xmrvizzy.skyblocker.skyblock.experiment.UltrasequencerSolver;
import me.xmrvizzy.skyblocker.skyblock.item.BackpackPreview;
import me.xmrvizzy.skyblocker.skyblock.item.CompactorDeletorPreview;
import me.xmrvizzy.skyblocker.skyblock.item.ItemProtection;
+import me.xmrvizzy.skyblocker.skyblock.item.ItemRarityBackgrounds;
import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup;
import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry;
import me.xmrvizzy.skyblocker.utils.Utils;
@@ -184,4 +185,9 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
private static boolean skyblocker$doesLoreContain(ItemStack stack, MinecraftClient client, String searchString) {
return stack.getTooltip(client.player, TooltipContext.BASIC).stream().map(Text::getString).anyMatch(line -> line.contains(searchString));
}
+
+ @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V"))
+ private void skyblocker$drawItemRarityBackground(DrawContext context, Slot slot, CallbackInfo ci) {
+ if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) ItemRarityBackgrounds.tryDraw(slot.getStack(), context, slot.x, slot.y);
+ }
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java
index c73ca2aa..3376907b 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java
@@ -1,17 +1,24 @@
package me.xmrvizzy.skyblocker.mixin;
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
import me.xmrvizzy.skyblocker.SkyblockerMod;
import me.xmrvizzy.skyblocker.config.SkyblockerConfigManager;
import me.xmrvizzy.skyblocker.skyblock.FancyStatusBars;
import me.xmrvizzy.skyblocker.skyblock.HotbarSlotLock;
+import me.xmrvizzy.skyblocker.skyblock.item.ItemCooldowns;
import me.xmrvizzy.skyblocker.skyblock.dungeon.DungeonMap;
+import me.xmrvizzy.skyblocker.skyblock.item.ItemRarityBackgrounds;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
+import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.hud.InGameHud;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
+import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@@ -32,10 +39,15 @@ public abstract class InGameHudMixin {
@Shadow
private int scaledWidth;
+ @Shadow
+ @Final
+ private MinecraftClient client;
+
@Inject(method = "renderHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHotbarItem(Lnet/minecraft/client/gui/DrawContext;IIFLnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;I)V", ordinal = 0))
- public void skyblocker$renderHotbarItemLock(float tickDelta, DrawContext context, CallbackInfo ci, @Local(ordinal = 4, name = "m") int index, @Local(ordinal = 5, name = "n") int x, @Local(ordinal = 6, name = "o") int y) {
- if (Utils.isOnSkyblock() && HotbarSlotLock.isLocked(index)) {
- context.drawTexture(SLOT_LOCK, x, y, 0, 0, 16, 16);
+ public void skyblocker$renderHotbarItemLockOrRarityBg(float tickDelta, DrawContext context, CallbackInfo ci, @Local(ordinal = 4, name = "m") int index, @Local(ordinal = 5, name = "n") int x, @Local(ordinal = 6, name = "o") int y, @Local PlayerEntity player) {
+ if (Utils.isOnSkyblock()) {
+ if (SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) ItemRarityBackgrounds.tryDraw(player.getInventory().main.get(index), context, x, y);
+ if (HotbarSlotLock.isLocked(index)) context.drawTexture(SLOT_LOCK, x, y, 0, 0, 16, 16);
}
}
@@ -61,9 +73,21 @@ public abstract class InGameHudMixin {
if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.bars.enableBars && !Utils.isInTheRift())
ci.cancel();
}
-
+
@Inject(method = "renderStatusEffectOverlay", at = @At("HEAD"), cancellable = true)
private void skyblocker$dontRenderStatusEffects(CallbackInfo ci) {
if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.hideStatusEffectOverlay) ci.cancel();
}
-} \ No newline at end of file
+
+ @ModifyExpressionValue(method = "renderCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getAttackCooldownProgress(F)F"))
+ private float skyblocker$modifyAttackIndicatorCooldown(float cooldownProgress) {
+ if (Utils.isOnSkyblock() && client.player != null) {
+ ItemStack stack = client.player.getMainHandStack();
+ if (ItemCooldowns.isOnCooldown(stack)) {
+ return ItemCooldowns.getItemCooldownEntry(stack).getRemainingCooldownPercent();
+ }
+ }
+
+ return cooldownProgress;
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfit.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfit.java
index 91be5248..ea54ff32 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfit.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfit.java
@@ -160,7 +160,7 @@ public class DungeonChestProfit {
private static Text getProfitText(int profit, boolean hasIncompleteData) {
SkyblockerConfig.DungeonChestProfit config = SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit;
- return getProfitText(profit, hasIncompleteData, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting);
+ return getProfitText(profit, hasIncompleteData, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor);
}
static Text getProfitText(int profit, boolean hasIncompleteData, int neutralThreshold, Formatting neutralColor, Formatting profitColor, Formatting lossColor, Formatting incompleteColor) {
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java
index dba066a5..6eb0623c 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CustomArmorTrims.java
@@ -8,7 +8,7 @@ import dev.isxander.yacl3.config.v2.api.SerialEntry;
import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import me.xmrvizzy.skyblocker.config.SkyblockerConfigManager;
-import me.xmrvizzy.skyblocker.utils.SkyblockEvents;
+import me.xmrvizzy.skyblocker.events.SkyblockEvents;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/ItemCooldowns.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/ItemCooldowns.java
new file mode 100644
index 00000000..dbe0c16e
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/ItemCooldowns.java
@@ -0,0 +1,115 @@
+package me.xmrvizzy.skyblocker.skyblock.item;
+
+import com.google.common.collect.ImmutableList;
+import me.xmrvizzy.skyblocker.config.SkyblockerConfigManager;
+import me.xmrvizzy.skyblocker.events.ClientPlayerBlockBreakEvent;
+import me.xmrvizzy.skyblocker.utils.ItemUtils;
+import net.fabricmc.fabric.api.event.player.UseItemCallback;
+import net.minecraft.block.BlockState;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.item.ItemStack;
+import net.minecraft.registry.tag.BlockTags;
+import net.minecraft.util.Hand;
+import net.minecraft.util.TypedActionResult;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ItemCooldowns {
+ private static final String JUNGLE_AXE_ID = "JUNGLE_AXE";
+ private static final String TREECAPITATOR_ID = "TREECAPITATOR_AXE";
+ private static final String GRAPPLING_HOOK_ID = "GRAPPLING_HOOK";
+ private static final ImmutableList<String> BAT_ARMOR_IDS = ImmutableList.of("BAT_PERSON_HELMET", "BAT_PERSON_CHESTPLATE", "BAT_PERSON_LEGGINGS", "BAT_PERSON_BOOTS");
+
+ private static final Map<String, CooldownEntry> ITEM_COOLDOWNS = new HashMap<>();
+
+ public static void init() {
+ ClientPlayerBlockBreakEvent.AFTER.register(ItemCooldowns::afterBlockBreak);
+ UseItemCallback.EVENT.register(ItemCooldowns::onItemInteract);
+ }
+
+ public static void afterBlockBreak(World world, PlayerEntity player, BlockPos pos, BlockState state) {
+ if (!SkyblockerConfigManager.get().general.itemCooldown.enableItemCooldowns) return;
+
+ String usedItemId = ItemUtils.getItemId(player.getMainHandStack());
+ if (usedItemId == null) return;
+
+ if (state.isIn(BlockTags.LOGS)) {
+ if (usedItemId.equals(JUNGLE_AXE_ID)) {
+ if (!isOnCooldown(JUNGLE_AXE_ID)) {
+ ITEM_COOLDOWNS.put(JUNGLE_AXE_ID, new CooldownEntry(2000));
+ }
+ } else if (usedItemId.equals(TREECAPITATOR_ID)) {
+ if (!isOnCooldown(TREECAPITATOR_ID)) {
+ ITEM_COOLDOWNS.put(TREECAPITATOR_ID, new CooldownEntry(2000));
+ }
+ }
+ }
+ }
+
+ private static TypedActionResult<ItemStack> onItemInteract(PlayerEntity player, World world, Hand hand) {
+ if (!SkyblockerConfigManager.get().general.itemCooldown.enableItemCooldowns) return TypedActionResult.pass(ItemStack.EMPTY);
+
+ String usedItemId = ItemUtils.getItemId(player.getMainHandStack());
+ if (usedItemId != null && usedItemId.equals(GRAPPLING_HOOK_ID) && player.fishHook != null) {
+ if (!isOnCooldown(GRAPPLING_HOOK_ID) && !isWearingBatArmor(player)) {
+ ITEM_COOLDOWNS.put(GRAPPLING_HOOK_ID, new CooldownEntry(2000));
+ }
+ }
+
+ return TypedActionResult.pass(ItemStack.EMPTY);
+ }
+
+ public static boolean isOnCooldown(ItemStack itemStack) {
+ return isOnCooldown(ItemUtils.getItemId(itemStack));
+ }
+
+ private static boolean isOnCooldown(String itemId) {
+ if (ITEM_COOLDOWNS.containsKey(itemId)) {
+ CooldownEntry cooldownEntry = ITEM_COOLDOWNS.get(itemId);
+ if (cooldownEntry.isOnCooldown()) {
+ return true;
+ } else {
+ ITEM_COOLDOWNS.remove(itemId);
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ public static CooldownEntry getItemCooldownEntry(ItemStack itemStack) {
+ return ITEM_COOLDOWNS.get(ItemUtils.getItemId(itemStack));
+ }
+
+ private static boolean isWearingBatArmor(PlayerEntity player) {
+ for (ItemStack stack : player.getArmorItems()) {
+ String itemId = ItemUtils.getItemId(stack);
+ if (!BAT_ARMOR_IDS.contains(itemId)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public record CooldownEntry(int cooldown, long startTime) {
+ public CooldownEntry(int cooldown) {
+ this(cooldown, System.currentTimeMillis());
+ }
+
+ public boolean isOnCooldown() {
+ return (this.startTime + this.cooldown) > System.currentTimeMillis();
+ }
+
+ public long getRemainingCooldown() {
+ long time = (this.startTime + this.cooldown) - System.currentTimeMillis();
+ return Math.max(time, 0);
+ }
+
+ public float getRemainingCooldownPercent() {
+ return this.isOnCooldown() ? (float) this.getRemainingCooldown() / cooldown : 0.0f;
+ }
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/ItemRarityBackgrounds.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/ItemRarityBackgrounds.java
new file mode 100644
index 00000000..837c209a
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/ItemRarityBackgrounds.java
@@ -0,0 +1,109 @@
+package me.xmrvizzy.skyblocker.skyblock.item;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import com.google.common.collect.ImmutableMap;
+import com.mojang.blaze3d.systems.RenderSystem;
+
+import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
+import me.xmrvizzy.skyblocker.SkyblockerMod;
+import me.xmrvizzy.skyblocker.config.SkyblockerConfigManager;
+import me.xmrvizzy.skyblocker.utils.Utils;
+import me.xmrvizzy.skyblocker.utils.scheduler.Scheduler;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.item.TooltipContext;
+import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.client.texture.Sprite;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NbtCompound;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+public class ItemRarityBackgrounds {
+ private static final Identifier RARITY_BG_TEX = new Identifier(SkyblockerMod.NAMESPACE, "item_rarity_background");
+ private static final Supplier<Sprite> SPRITE = () -> MinecraftClient.getInstance().getGuiAtlasManager().getSprite(RARITY_BG_TEX);
+ private static final ImmutableMap<String, SkyblockItemRarity> LORE_RARITIES = ImmutableMap.ofEntries(
+ Map.entry("ADMIN", SkyblockItemRarity.ADMIN),
+ Map.entry("SPECIAL", SkyblockItemRarity.SPECIAL), //Very special is the same color so this will cover it
+ Map.entry("DIVINE", SkyblockItemRarity.DIVINE),
+ Map.entry("MYTHIC", SkyblockItemRarity.MYTHIC),
+ Map.entry("LEGENDARY", SkyblockItemRarity.LEGENDARY),
+ Map.entry("LEGENJERRY", SkyblockItemRarity.LEGENDARY),
+ Map.entry("EPIC", SkyblockItemRarity.EPIC),
+ Map.entry("RARE", SkyblockItemRarity.RARE),
+ Map.entry("UNCOMMON", SkyblockItemRarity.UNCOMMON),
+ Map.entry("COMMON", SkyblockItemRarity.COMMON)
+ );
+ private static final Int2ReferenceOpenHashMap<SkyblockItemRarity> CACHE = new Int2ReferenceOpenHashMap<>();
+
+ public static void init() {
+ //Clear the cache every 5 minutes, ints are very compact!
+ Scheduler.INSTANCE.scheduleCyclic(CACHE::clear, 4800);
+
+ //Clear cache after a screen where items can be upgraded in rarity closes
+ ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
+ String title = screen.getTitle().getString();
+
+ if (Utils.isOnSkyblock() && (title.equals("The Hex") || title.equals("Craft Item") || title.equals("Anvil") || title.equals("Reforge Anvil"))) {
+ ScreenEvents.remove(screen).register(screen1 -> CACHE.clear());
+ }
+ });
+ }
+
+ public static void tryDraw(ItemStack stack, DrawContext context, int x, int y) {
+ MinecraftClient client = MinecraftClient.getInstance();
+
+ if (client.player != null) {
+ SkyblockItemRarity itemRarity = getItemRarity(stack, client.player);
+
+ if (itemRarity != null) draw(context, x, y, itemRarity);
+ }
+ }
+
+ private static SkyblockItemRarity getItemRarity(ItemStack stack, ClientPlayerEntity player) {
+ if (stack == null || stack.isEmpty()) return null;
+
+ int hashCode = 0;
+ NbtCompound nbt = stack.getNbt();
+
+ if (nbt != null && nbt.contains("ExtraAttributes")) {
+ NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes");
+ String itemUuid = extraAttributes.getString("uuid");
+
+ //If the item has an uuid, then use the hash code of the uuid otherwise use the identity hash code of the stack
+ hashCode = itemUuid.isEmpty() ? System.identityHashCode(stack) : itemUuid.hashCode();
+ }
+
+ if (CACHE.containsKey(hashCode)) return CACHE.get(hashCode);
+
+ List<Text> tooltip = stack.getTooltip(player, TooltipContext.BASIC);
+ String[] stringifiedTooltip = tooltip.stream().map(Text::getString).toArray(String[]::new);
+
+ for (String rarityString : LORE_RARITIES.keySet()) {
+ if (Arrays.stream(stringifiedTooltip).anyMatch(line -> line.contains(rarityString))) {
+ SkyblockItemRarity rarity = LORE_RARITIES.get(rarityString);
+
+ CACHE.put(hashCode, rarity);
+ return rarity;
+ }
+ }
+
+ CACHE.put(hashCode, null);
+ return null;
+ }
+
+ private static void draw(DrawContext context, int x, int y, SkyblockItemRarity rarity) {
+ //Enable blending to handle HUD translucency
+ RenderSystem.enableBlend();
+ RenderSystem.defaultBlendFunc();
+
+ context.drawSprite(x, y, 0, 16, 16, SPRITE.get(), rarity.r, rarity.g, rarity.b, SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgroundsOpacity);
+
+ RenderSystem.disableBlend();
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/SkyblockItemRarity.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/SkyblockItemRarity.java
new file mode 100644
index 00000000..f7ff1fb9
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/SkyblockItemRarity.java
@@ -0,0 +1,29 @@
+package me.xmrvizzy.skyblocker.skyblock.item;
+
+import net.minecraft.util.Formatting;
+
+public enum SkyblockItemRarity {
+ ADMIN(Formatting.DARK_RED),
+ VERY_SPECIAL(Formatting.RED),
+ SPECIAL(Formatting.RED),
+ DIVINE(Formatting.AQUA),
+ MYTHIC(Formatting.LIGHT_PURPLE),
+ LEGENDARY(Formatting.GOLD),
+ EPIC(Formatting.DARK_PURPLE),
+ RARE(Formatting.BLUE),
+ UNCOMMON(Formatting.GREEN),
+ COMMON(Formatting.WHITE);
+
+ public final float r;
+ public final float g;
+ public final float b;
+
+ SkyblockItemRarity(Formatting formatting) {
+ @SuppressWarnings("DataFlowIssue")
+ int rgb = formatting.getColorValue();
+
+ this.r = ((rgb >> 16) & 0xFF) / 255f;
+ this.g = ((rgb >> 8) & 0xFF) / 255f;
+ this.b = (rgb & 0xFF) / 255f;
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ResultButtonWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ResultButtonWidget.java
index 19f656e5..61a9aa20 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ResultButtonWidget.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ResultButtonWidget.java
@@ -15,7 +15,7 @@ import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class ResultButtonWidget extends ClickableWidget {
- private static final Identifier BACKGROUND_TEXTURE = new Identifier("textures/gui/recipe_book.png");
+ private static final Identifier BACKGROUND_TEXTURE = new Identifier("recipe_book/slot_craftable");
protected ItemStack itemStack = null;
@@ -38,7 +38,7 @@ public class ResultButtonWidget extends ClickableWidget {
public void renderButton(DrawContext context, int mouseX, int mouseY, float delta) {
MinecraftClient client = MinecraftClient.getInstance();
// this.drawTexture(matrices, this.x, this.y, 29, 206, this.width, this.height);
- context.drawTexture(BACKGROUND_TEXTURE, this.getX(), this.getY(), 29, 206, this.getWidth(), this.getHeight());
+ context.drawGuiTexture(BACKGROUND_TEXTURE, this.getX(), this.getY(), this.getWidth(), this.getHeight());
// client.getItemRenderer().renderInGui(this.itemStack, this.x + 4, this.y + 4);
context.drawItem(this.itemStack, this.getX() + 4, this.getY() + 4);
// client.getItemRenderer().renderGuiItemOverlay(client.textRenderer, itemStack, this.x + 4, this.y + 4);
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/ItemUtils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/ItemUtils.java
index 30c20524..b8192b45 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/ItemUtils.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/ItemUtils.java
@@ -92,6 +92,20 @@ public class ItemUtils {
}
}
+ public static String getItemId(ItemStack itemStack) {
+ if (itemStack == null) return null;
+
+ NbtCompound nbt = itemStack.getNbt();
+ if (nbt != null && nbt.contains("ExtraAttributes")) {
+ NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes");
+ if (extraAttributes.contains("id")) {
+ return extraAttributes.getString("id");
+ }
+ }
+
+ return null;
+ }
+
public record Durability(int current, int max) {
}
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
index b0fb6edf..20edfca2 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
@@ -2,6 +2,7 @@ package me.xmrvizzy.skyblocker.utils;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
+import me.xmrvizzy.skyblocker.events.SkyblockEvents;
import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip;
import me.xmrvizzy.skyblocker.skyblock.rift.TheRift;
import me.xmrvizzy.skyblocker.utils.scheduler.MessageScheduler;
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/discord/DiscordRPCManager.java b/src/main/java/me/xmrvizzy/skyblocker/utils/discord/DiscordRPCManager.java
index 39d91bba..6196fec0 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/discord/DiscordRPCManager.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/discord/DiscordRPCManager.java
@@ -2,7 +2,7 @@ package me.xmrvizzy.skyblocker.utils.discord;
import me.xmrvizzy.skyblocker.config.SkyblockerConfigManager;
-import me.xmrvizzy.skyblocker.utils.SkyblockEvents;
+import me.xmrvizzy.skyblocker.events.SkyblockEvents;
import me.xmrvizzy.skyblocker.utils.Utils;
import meteordevelopment.discordipc.DiscordIPC;
import meteordevelopment.discordipc.RichPresence;
@@ -34,7 +34,7 @@ public class DiscordRPCManager {
}
/**
- * Checks the {@link SkyblockerConfigManager.RichPresence#customMessage custom message}, updates {@link #cycleCount} if enabled, and updates rich presence.
+ * Checks the {@link me.xmrvizzy.skyblocker.config.SkyblockerConfig.RichPresence#customMessage custom message}, updates {@link #cycleCount} if enabled, and updates rich presence.
*/
public static void updateDataAndPresence() {
// If the custom message is empty, discord will keep the last message, this is can serve as a default if the user doesn't want a custom message
@@ -58,16 +58,16 @@ public class DiscordRPCManager {
* <p>
* When the {@link #updateTask previous update} does not exist or {@link CompletableFuture#isDone() has completed}:
* <p>
- * Connects to discord if {@link SkyblockerConfigManager.RichPresence#enableRichPresence rich presence is enabled},
+ * Connects to discord if {@link me.xmrvizzy.skyblocker.config.SkyblockerConfig.RichPresence#enableRichPresence rich presence is enabled},
* the player {@link Utils#isOnSkyblock() is on Skyblock}, and {@link DiscordIPC#isConnected() discord is not already connected}.
- * Updates the presence if {@link SkyblockerConfigManager.RichPresence#enableRichPresence rich presence is enabled}
+ * Updates the presence if {@link me.xmrvizzy.skyblocker.config.SkyblockerConfig.RichPresence#enableRichPresence rich presence is enabled}
* and the player {@link Utils#isOnSkyblock() is on Skyblock}.
- * Stops the connection if {@link SkyblockerConfigManager.RichPresence#enableRichPresence rich presence is disabled}
+ * Stops the connection if {@link me.xmrvizzy.skyblocker.config.SkyblockerConfig.RichPresence#enableRichPresence rich presence is disabled}
* or the player {@link Utils#isOnSkyblock() is not on Skyblock} and {@link DiscordIPC#isConnected() discord is connected}.
* Saves the update task in {@link #updateTask}
*
* @param initialization whether this is the first time the presence is being updates. If {@code true}, a message will be logged
- * if {@link SkyblockerConfigManager.RichPresence#enableRichPresence rich presence is disabled}.
+ * if {@link me.xmrvizzy.skyblocker.config.SkyblockerConfig.RichPresence#enableRichPresence rich presence is disabled}.
*/
private static void initAndUpdatePresence(boolean initialization) {
if (updateTask == null || updateTask.isDone()) {
diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json
index 76b6e768..f889595e 100644
--- a/src/main/resources/assets/skyblocker/lang/en_us.json
+++ b/src/main/resources/assets/skyblocker/lang/en_us.json
@@ -38,9 +38,11 @@
"text.autoconfig.skyblocker.option.general.fairySouls.highlightFoundSouls": "Highlight found fairy souls",
"text.autoconfig.skyblocker.option.general.fairySouls.highlightOnlyNearbySouls": "Only highlight nearby fairy souls",
"text.autoconfig.skyblocker.option.general.fairySouls.highlightOnlyNearbySouls.@Tooltip": "When enabled only fairy souls in a radius of 50 blocks are highlighted",
+ "text.autoconfig.skyblocker.option.general.itemCooldown": "Item Cooldown",
+ "text.autoconfig.skyblocker.option.general.itemCooldown.enableItemCooldowns": "Enable Item Cooldown",
"text.autoconfig.skyblocker.option.general.shortcuts": "Shortcuts",
"text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts": "Enable Shortcuts",
- "text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts.@Tooltip": "Only works on Hypixel. Edit shortcuts with \"/skyblocker shortcuts\". At least one of the following options must be enabled for this to take effect.",
+ "text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts.@Tooltip": "Works anywhere, even in vanilla! Edit shortcuts with \"/skyblocker shortcuts\". At least one of the following options must be enabled for this to take effect.",
"text.autoconfig.skyblocker.option.general.shortcuts.enableCommandShortcuts": "Enable Command Shortcuts",
"text.autoconfig.skyblocker.option.general.shortcuts.enableCommandShortcuts.@Tooltip": "Shortcuts for commands consisting of only one word. Edit shortcuts with \"/skyblocker shortcuts\". Shortcuts must be enabled for this to take effect.",
"text.autoconfig.skyblocker.option.general.shortcuts.enableCommandArgShortcuts": "Enable Command Argument Shortcuts",
@@ -76,6 +78,9 @@
"text.autoconfig.skyblocker.option.general.itemInfoDisplay": "Item Info Display",
"text.autoconfig.skyblocker.option.general.itemInfoDisplay.attributeShardInfo": "Attribute Shard Info",
"text.autoconfig.skyblocker.option.general.itemInfoDisplay.attributeShardInfo.@Tooltip": "Displays the attribute's level as the stack count and the initials of the attribute's name.",
+ "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgrounds": "Item Rarity Backgrounds",
+ "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgrounds.@Tooltip": "Displays a colored background behind an item, the color represents the item's rarity.",
+ "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgroundsOpacity": "Item Rarity Backgrounds Opacity",
"text.autoconfig.skyblocker.option.general.specialEffects": "Special Effects",
"text.autoconfig.skyblocker.option.general.specialEffects.rareDungeonDropEffects": "Rare Dungeon Drop Effects",
"text.autoconfig.skyblocker.option.general.specialEffects.rareDungeonDropEffects.@Tooltip": "Adds a special visual effect triggered upon obtaining rare dungeon loot!",
diff --git a/src/main/resources/assets/skyblocker/textures/gui/sprites/item_rarity_background.png b/src/main/resources/assets/skyblocker/textures/gui/sprites/item_rarity_background.png
new file mode 100644
index 00000000..fd8e8604
--- /dev/null
+++ b/src/main/resources/assets/skyblocker/textures/gui/sprites/item_rarity_background.png
Binary files differ
diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json
index 05759d84..4afb2bbd 100644
--- a/src/main/resources/skyblocker.mixins.json
+++ b/src/main/resources/skyblocker.mixins.json
@@ -8,6 +8,7 @@
"ArmorTrimMixin",
"BatEntityMixin",
"ClientPlayerEntityMixin",
+ "ClientPlayerInteractionManagerMixin",
"ClientPlayNetworkHandlerMixin",
"DrawContextMixin",
"DyeableItemMixin",
@@ -28,15 +29,15 @@
"YggdrasilMinecraftSessionServiceMixin",
"YggdrasilServicesKeyInfoMixin",
"accessor.BeaconBlockEntityRendererInvoker",
+ "accessor.DrawContextInvoker",
"accessor.FrustumInvoker",
"accessor.HandledScreenAccessor",
"accessor.PlayerListHudAccessor",
"accessor.RecipeBookWidgetAccessor",
"accessor.ScreenAccessor",
- "accessor.WorldRendererAccessor",
- "accessor.DrawContextInvoker"
+ "accessor.WorldRendererAccessor"
],
"injectors": {
"defaultRequire": 1
}
-} \ No newline at end of file
+}
diff --git a/src/test/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfitTest.java b/src/test/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfitTest.java
index 7a130b5a..9ff1e154 100644
--- a/src/test/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfitTest.java
+++ b/src/test/java/me/xmrvizzy/skyblocker/skyblock/dungeon/DungeonChestProfitTest.java
@@ -8,15 +8,15 @@ public class DungeonChestProfitTest {
@Test
void testProfitText() {
SkyblockerConfig.DungeonChestProfit config = new SkyblockerConfig.DungeonChestProfit();
- Assertions.assertEquals("literal{ 0}[style={color=dark_gray}]", DungeonChestProfit.getProfitText(0, false, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
- Assertions.assertEquals("literal{ 0}[style={color=blue}]", DungeonChestProfit.getProfitText(0, true, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
- Assertions.assertEquals("literal{ +10}[style={color=dark_gray}]", DungeonChestProfit.getProfitText(10, false, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
- Assertions.assertEquals("literal{ +10}[style={color=blue}]", DungeonChestProfit.getProfitText(10, true, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
- Assertions.assertEquals("literal{ -10}[style={color=dark_gray}]", DungeonChestProfit.getProfitText(-10, false, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
- Assertions.assertEquals("literal{ -10}[style={color=blue}]", DungeonChestProfit.getProfitText(-10, true, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
- Assertions.assertEquals("literal{ +10,000}[style={color=dark_green}]", DungeonChestProfit.getProfitText(10000, false, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
- Assertions.assertEquals("literal{ +10,000}[style={color=blue}]", DungeonChestProfit.getProfitText(10000, true, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
- Assertions.assertEquals("literal{ -10,000}[style={color=red}]", DungeonChestProfit.getProfitText(-10000, false, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
- Assertions.assertEquals("literal{ -10,000}[style={color=blue}]", DungeonChestProfit.getProfitText(-10000, true, config.neutralThreshold, config.neutralColor.formatting, config.profitColor.formatting, config.lossColor.formatting, config.incompleteColor.formatting).toString());
+ Assertions.assertEquals("literal{ 0}[style={color=dark_gray}]", DungeonChestProfit.getProfitText(0, false, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
+ Assertions.assertEquals("literal{ 0}[style={color=blue}]", DungeonChestProfit.getProfitText(0, true, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
+ Assertions.assertEquals("literal{ +10}[style={color=dark_gray}]", DungeonChestProfit.getProfitText(10, false, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
+ Assertions.assertEquals("literal{ +10}[style={color=blue}]", DungeonChestProfit.getProfitText(10, true, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
+ Assertions.assertEquals("literal{ -10}[style={color=dark_gray}]", DungeonChestProfit.getProfitText(-10, false, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
+ Assertions.assertEquals("literal{ -10}[style={color=blue}]", DungeonChestProfit.getProfitText(-10, true, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
+ Assertions.assertEquals("literal{ +10,000}[style={color=dark_green}]", DungeonChestProfit.getProfitText(10000, false, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
+ Assertions.assertEquals("literal{ +10,000}[style={color=blue}]", DungeonChestProfit.getProfitText(10000, true, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
+ Assertions.assertEquals("literal{ -10,000}[style={color=red}]", DungeonChestProfit.getProfitText(-10000, false, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
+ Assertions.assertEquals("literal{ -10,000}[style={color=blue}]", DungeonChestProfit.getProfitText(-10000, true, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor).toString());
}
}