aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/SkyblockerMod.java12
-rw-r--r--src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java5
-rw-r--r--src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java6
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java15
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java23
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/MiningCategory.java50
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java643
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java68
-rw-r--r--src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java6
-rw-r--r--src/main/java/de/hysky/skyblocker/config/configs/ForagingConfig.java13
-rw-r--r--src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java34
-rw-r--r--src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java137
-rw-r--r--src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java31
-rw-r--r--src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFix.java16
-rw-r--r--src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixer.java96
-rw-r--r--src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix1.java211
-rw-r--r--src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix2QuickNav.java38
-rw-r--r--src/main/java/de/hysky/skyblocker/config/datafixer/ConfigSchema.java29
-rw-r--r--src/main/java/de/hysky/skyblocker/debug/Debug.java27
-rw-r--r--src/main/java/de/hysky/skyblocker/events/SkyblockEvents.java13
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java23
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java24
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java48
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/SignEditScreenMixin.java44
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/HandledScreenAccessor.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java86
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionViewScreen.java21
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java15
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/calculators/CalculatorCommand.java56
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/calculators/SignCalculator.java66
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java10
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/LightsOnTerminal.java37
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java13
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java13
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/TerminalSolver.java10
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dwarven/CommissionLabels.java99
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsWaypoint.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java9
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dwarven/MiningLocationLabel.java157
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/foraging/ModernForagingIsland.java8
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java11
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java38
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java61
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Calculator.java208
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/ItemUtils.java5
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Location.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Utils.java12
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/datafixer/JsonHelper.java107
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolver.java7
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java11
52 files changed, 1890 insertions, 798 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
index 3336cefb..0dc1b409 100644
--- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
+++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
@@ -3,10 +3,12 @@ package de.hysky.skyblocker;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import de.hysky.skyblocker.config.datafixer.ConfigDataFixer;
import de.hysky.skyblocker.config.ImageRepoLoader;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.debug.Debug;
import de.hysky.skyblocker.skyblock.*;
+import de.hysky.skyblocker.skyblock.calculators.CalculatorCommand;
import de.hysky.skyblocker.skyblock.chat.ChatRuleAnnouncementScreen;
import de.hysky.skyblocker.skyblock.chat.ChatRulesHandler;
import de.hysky.skyblocker.skyblock.crimson.kuudra.Kuudra;
@@ -17,10 +19,7 @@ import de.hysky.skyblocker.skyblock.dungeon.puzzle.boulder.Boulder;
import de.hysky.skyblocker.skyblock.dungeon.puzzle.waterboard.Waterboard;
import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager;
import de.hysky.skyblocker.skyblock.dungeon.secrets.SecretsTracker;
-import de.hysky.skyblocker.skyblock.dwarven.CrystalsHud;
-import de.hysky.skyblocker.skyblock.dwarven.CrystalsLocationsManager;
-import de.hysky.skyblocker.skyblock.dwarven.DwarvenHud;
-import de.hysky.skyblocker.skyblock.dwarven.MetalDetector;
+import de.hysky.skyblocker.skyblock.dwarven.*;
import de.hysky.skyblocker.skyblock.end.BeaconHighlighter;
import de.hysky.skyblocker.skyblock.end.EnderNodes;
import de.hysky.skyblocker.skyblock.end.TheEnd;
@@ -77,6 +76,7 @@ public class SkyblockerMod implements ClientModInitializer {
public static final String VERSION = SKYBLOCKER_MOD.getMetadata().getVersion().getFriendlyString();
public static final Path CONFIG_DIR = FabricLoader.getInstance().getConfigDir().resolve(NAMESPACE);
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
+ public static final Gson GSON_COMPACT = new GsonBuilder().create();
private static SkyblockerMod INSTANCE;
public final ContainerSolverManager containerSolverManager = new ContainerSolverManager();
public final StatusBarTracker statusBarTracker = new StatusBarTracker();
@@ -101,6 +101,7 @@ public class SkyblockerMod implements ClientModInitializer {
@Override
public void onInitializeClient() {
ClientTickEvents.END_CLIENT_TICK.register(this::tick);
+ ConfigDataFixer.apply();
Utils.init();
SkyblockerConfigManager.init();
SkyblockerScreen.initClass();
@@ -119,10 +120,10 @@ public class SkyblockerMod implements ClientModInitializer {
EnderNodes.init();
OrderedWaypoints.init();
BackpackPreview.init();
- QuickNav.init();
ItemCooldowns.init();
TabHud.init();
DwarvenHud.init();
+ CommissionLabels.init();
CrystalsHud.init();
FarmingHud.init();
LowerSensitivity.init();
@@ -132,6 +133,7 @@ public class SkyblockerMod implements ClientModInitializer {
Shortcuts.init();
ChatRulesHandler.init();
ChatRuleAnnouncementScreen.init();
+ CalculatorCommand.init();
DiscordRPCManager.init();
LividColor.init();
FishingHelper.init();
diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
index c591ba14..9c495382 100644
--- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
@@ -5,7 +5,7 @@ import dev.isxander.yacl3.config.v2.api.SerialEntry;
public class SkyblockerConfig {
@SerialEntry
- public int version = 2;
+ public int version = SkyblockerConfigManager.CONFIG_VERSION;
@SerialEntry
public GeneralConfig general = new GeneralConfig();
@@ -20,6 +20,9 @@ public class SkyblockerConfig {
public DungeonsConfig dungeons = new DungeonsConfig();
@SerialEntry
+ public ForagingConfig foraging = new ForagingConfig();
+
+ @SerialEntry
public CrimsonIsleConfig crimsonIsle = new CrimsonIsleConfig();
@SerialEntry
diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java
index 4b8e56df..dd406b8a 100644
--- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java
+++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java
@@ -26,10 +26,11 @@ import java.lang.StackWalker.Option;
import java.nio.file.Path;
public class SkyblockerConfigManager {
- private static final Path PATH = FabricLoader.getInstance().getConfigDir().resolve("skyblocker-2.json");
+ public static final int CONFIG_VERSION = 3;
+ private static final Path CONFIG_FILE = FabricLoader.getInstance().getConfigDir().resolve("skyblocker.json");
private static final ConfigClassHandler<SkyblockerConfig> HANDLER = ConfigClassHandler.createBuilder(SkyblockerConfig.class)
.serializer(config -> GsonConfigSerializerBuilder.create(config)
- .setPath(PATH)
+ .setPath(CONFIG_FILE)
.setJson5(false)
.appendGsonBuilder(builder -> builder
.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
@@ -74,6 +75,7 @@ public class SkyblockerConfigManager {
.category(UIAndVisualsCategory.create(defaults, config))
.category(HelperCategory.create(defaults, config))
.category(DungeonsCategory.create(defaults, config))
+ //.category(ForagingCategory.create(defaults, config))
.category(CrimsonIsleCategory.create(defaults, config))
.category(MiningCategory.create(defaults, config))
.category(FarmingCategory.create(defaults, config))
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java
index d44ab490..28ace441 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java
@@ -67,6 +67,14 @@ public class DungeonsCategory {
newValue -> config.dungeons.allowDroppingProtectedItems = newValue)
.controller(ConfigUtils::createBooleanController)
.build())
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("skyblocker.config.dungeons.hideSoulweaverSkulls"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.dungeons.hideSoulweaverSkulls.@Tooltip")))
+ .binding(defaults.dungeons.hideSoulweaverSkulls,
+ () -> config.dungeons.hideSoulweaverSkulls,
+ newValue -> config.dungeons.hideSoulweaverSkulls = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
// Map
.group(OptionGroup.createBuilder()
@@ -252,6 +260,13 @@ public class DungeonsCategory {
newValue -> config.dungeons.terminals.solveStartsWith = newValue)
.controller(ConfigUtils::createBooleanController)
.build())
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("skyblocker.config.dungeons.terminals.blockIncorrectClicks"))
+ .binding(defaults.dungeons.terminals.blockIncorrectClicks,
+ () -> config.dungeons.terminals.blockIncorrectClicks,
+ newValue -> config.dungeons.terminals.blockIncorrectClicks = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
.build())
// Dungeon Secret Waypoints
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java
new file mode 100644
index 00000000..d5c844b7
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/config/categories/ForagingCategory.java
@@ -0,0 +1,23 @@
+package de.hysky.skyblocker.config.categories;
+
+import de.hysky.skyblocker.config.SkyblockerConfig;
+import dev.isxander.yacl3.api.ConfigCategory;
+import net.minecraft.text.Text;
+
+public class ForagingCategory {
+
+ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig config) {
+ return ConfigCategory.createBuilder()
+ .name(Text.translatable("skyblocker.config.foraging"))
+
+ //Modern Foraging island
+
+ //Hunting - YACL doesn't like empty option groups
+ /*.group(OptionGroup.createBuilder()
+ .name(Text.translatable("skyblocker.config.foraging.hunting"))
+
+ .build())*/
+
+ .build();
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/MiningCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/MiningCategory.java
index 8809ba44..8dc587fd 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/MiningCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/MiningCategory.java
@@ -160,6 +160,56 @@ public class MiningCategory {
.build())
.build())
+
+ //commission waypoints
+ .group(OptionGroup.createBuilder()
+ .name(Text.translatable("skyblocker.config.mining.commissionWaypoints"))
+ .collapsed(false)
+ .option(Option.<MiningConfig.CommissionWaypointMode>createBuilder()
+ .name(Text.translatable("skyblocker.config.mining.commissionWaypoints.mode"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[0]"),
+ Text.translatable("skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[1]"),
+ Text.translatable("skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[2]"),
+ Text.translatable("skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[3]"),
+ Text.translatable("skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[4]")))
+ .binding(defaults.mining.commissionWaypoints.mode,
+ () -> config.mining.commissionWaypoints.mode,
+ newValue -> config.mining.commissionWaypoints.mode = newValue)
+ .controller(ConfigUtils::createEnumCyclingListController)
+ .build())
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("skyblocker.config.mining.commissionWaypoints.useColor"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.mining.commissionWaypoints.useColor.@Tooltip")))
+ .binding(defaults.mining.commissionWaypoints.useColor,
+ () -> config.mining.commissionWaypoints.useColor,
+ newValue -> config.mining.commissionWaypoints.useColor = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
+ .option(Option.<Float>createBuilder()
+ .name(Text.translatable("skyblocker.config.mining.commissionWaypoints.textScale"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.mining.commissionWaypoints.textScale.@Tooltip")))
+ .binding(defaults.mining.commissionWaypoints.textScale,
+ () -> config.mining.commissionWaypoints.textScale,
+ newValue -> config.mining.commissionWaypoints.textScale = newValue)
+ .controller(FloatFieldControllerBuilder::create)
+ .build())
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("skyblocker.config.mining.commissionWaypoints.showBaseCamp"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.mining.commissionWaypoints.showBaseCamp.@Tooltip")))
+ .binding(defaults.mining.commissionWaypoints.showBaseCamp,
+ () -> config.mining.commissionWaypoints.showBaseCamp,
+ newValue -> config.mining.commissionWaypoints.showBaseCamp = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("skyblocker.config.mining.commissionWaypoints.showEmissary"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.mining.commissionWaypoints.showEmissary.@Tooltip")))
+ .binding(defaults.mining.commissionWaypoints.showEmissary,
+ () -> config.mining.commissionWaypoints.showEmissary,
+ newValue -> config.mining.commissionWaypoints.showEmissary = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
+ .build())
.build();
}
}
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java
index 1200261d..98e5511c 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java
@@ -2,16 +2,18 @@ package de.hysky.skyblocker.config.categories;
import de.hysky.skyblocker.config.ConfigUtils;
import de.hysky.skyblocker.config.SkyblockerConfig;
+import de.hysky.skyblocker.config.configs.QuickNavigationConfig;
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.controller.IntegerFieldControllerBuilder;
+import dev.isxander.yacl3.api.controller.ItemControllerBuilder;
import dev.isxander.yacl3.api.controller.StringControllerBuilder;
+import net.minecraft.item.Item;
import net.minecraft.text.Text;
public class QuickNavigationCategory {
-
public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig config) {
return ConfigCategory.createBuilder()
.name(Text.translatable("skyblocker.config.quickNav"))
@@ -25,594 +27,71 @@ public class QuickNavigationCategory {
.controller(ConfigUtils::createBooleanController)
.build())
- //Button 1
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 1))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button1.render,
- () -> config.quickNav.button1.render,
- newValue -> config.quickNav.button1.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button1.item.id,
- () -> config.quickNav.button1.item.id,
- newValue -> config.quickNav.button1.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button1.item.count,
- () -> config.quickNav.button1.item.count,
- newValue -> config.quickNav.button1.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button1.item.nbt,
- () -> config.quickNav.button1.item.nbt,
- newValue -> config.quickNav.button1.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button1.uiTitle,
- () -> config.quickNav.button1.uiTitle,
- newValue -> config.quickNav.button1.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button1.clickEvent,
- () -> config.quickNav.button1.clickEvent,
- newValue -> config.quickNav.button1.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .build())
-
- //Button 2
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 2))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button2.render,
- () -> config.quickNav.button2.render,
- newValue -> config.quickNav.button2.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button2.item.id,
- () -> config.quickNav.button2.item.id,
- newValue -> config.quickNav.button2.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button2.item.count,
- () -> config.quickNav.button2.item.count,
- newValue -> config.quickNav.button2.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button2.item.nbt,
- () -> config.quickNav.button2.item.nbt,
- newValue -> config.quickNav.button2.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button2.uiTitle,
- () -> config.quickNav.button2.uiTitle,
- newValue -> config.quickNav.button2.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button2.clickEvent,
- () -> config.quickNav.button2.clickEvent,
- newValue -> config.quickNav.button2.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .build())
-
- //Button 3
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 3))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button3.render,
- () -> config.quickNav.button3.render,
- newValue -> config.quickNav.button3.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button3.item.id,
- () -> config.quickNav.button3.item.id,
- newValue -> config.quickNav.button3.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button3.item.count,
- () -> config.quickNav.button3.item.count,
- newValue -> config.quickNav.button3.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button3.item.nbt,
- () -> config.quickNav.button3.item.nbt,
- newValue -> config.quickNav.button3.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button3.uiTitle,
- () -> config.quickNav.button3.uiTitle,
- newValue -> config.quickNav.button3.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button3.clickEvent,
- () -> config.quickNav.button3.clickEvent,
- newValue -> config.quickNav.button3.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .build())
-
- //Button 4
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 4))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button4.render,
- () -> config.quickNav.button4.render,
- newValue -> config.quickNav.button4.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button4.item.id,
- () -> config.quickNav.button4.item.id,
- newValue -> config.quickNav.button4.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button4.item.count,
- () -> config.quickNav.button4.item.count,
- newValue -> config.quickNav.button4.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button4.item.nbt,
- () -> config.quickNav.button4.item.nbt,
- newValue -> config.quickNav.button4.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button4.uiTitle,
- () -> config.quickNav.button4.uiTitle,
- newValue -> config.quickNav.button4.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button4.clickEvent,
- () -> config.quickNav.button4.clickEvent,
- newValue -> config.quickNav.button4.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .build())
-
- //Button 5
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 5))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button5.render,
- () -> config.quickNav.button5.render,
- newValue -> config.quickNav.button5.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button5.item.id,
- () -> config.quickNav.button5.item.id,
- newValue -> config.quickNav.button5.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button5.item.count,
- () -> config.quickNav.button5.item.count,
- newValue -> config.quickNav.button5.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button5.item.nbt,
- () -> config.quickNav.button5.item.nbt,
- newValue -> config.quickNav.button5.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button5.uiTitle,
- () -> config.quickNav.button5.uiTitle,
- newValue -> config.quickNav.button5.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button5.clickEvent,
- () -> config.quickNav.button5.clickEvent,
- newValue -> config.quickNav.button5.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .build())
-
- //Button 6
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 6))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button6.render,
- () -> config.quickNav.button6.render,
- newValue -> config.quickNav.button6.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button6.item.id,
- () -> config.quickNav.button6.item.id,
- newValue -> config.quickNav.button6.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button6.item.count,
- () -> config.quickNav.button6.item.count,
- newValue -> config.quickNav.button6.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button6.item.nbt,
- () -> config.quickNav.button6.item.nbt,
- newValue -> config.quickNav.button6.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button6.uiTitle,
- () -> config.quickNav.button6.uiTitle,
- newValue -> config.quickNav.button6.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button6.clickEvent,
- () -> config.quickNav.button6.clickEvent,
- newValue -> config.quickNav.button6.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .build())
+ //Buttons
+ .group(quickNavButton(defaults.quickNav.button1, config.quickNav.button1, 1))
+ .group(quickNavButton(defaults.quickNav.button2, config.quickNav.button2, 2))
+ .group(quickNavButton(defaults.quickNav.button3, config.quickNav.button3, 3))
+ .group(quickNavButton(defaults.quickNav.button4, config.quickNav.button4, 4))
+ .group(quickNavButton(defaults.quickNav.button5, config.quickNav.button5, 5))
+ .group(quickNavButton(defaults.quickNav.button6, config.quickNav.button6, 6))
+ .group(quickNavButton(defaults.quickNav.button7, config.quickNav.button7, 7))
+ .group(quickNavButton(defaults.quickNav.button8, config.quickNav.button8, 8))
+ .group(quickNavButton(defaults.quickNav.button9, config.quickNav.button9, 9))
+ .group(quickNavButton(defaults.quickNav.button10, config.quickNav.button10, 10))
+ .group(quickNavButton(defaults.quickNav.button11, config.quickNav.button11, 11))
+ .group(quickNavButton(defaults.quickNav.button12, config.quickNav.button12, 12))
+ .group(quickNavButton(defaults.quickNav.button13, config.quickNav.button13, 13))
+ .group(quickNavButton(defaults.quickNav.button14, config.quickNav.button14, 14))
+ .build();
+ }
- //Button 7
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 7))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button7.render,
- () -> config.quickNav.button7.render,
- newValue -> config.quickNav.button7.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button7.item.id,
- () -> config.quickNav.button7.item.id,
- newValue -> config.quickNav.button7.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button7.item.count,
- () -> config.quickNav.button7.item.count,
- newValue -> config.quickNav.button7.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button7.item.nbt,
- () -> config.quickNav.button7.item.nbt,
- newValue -> config.quickNav.button7.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button7.uiTitle,
- () -> config.quickNav.button7.uiTitle,
- newValue -> config.quickNav.button7.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button7.clickEvent,
- () -> config.quickNav.button7.clickEvent,
- newValue -> config.quickNav.button7.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
+ private static OptionGroup quickNavButton(QuickNavigationConfig.QuickNavItem defaultButton, QuickNavigationConfig.QuickNavItem button, int index) {
+ return OptionGroup.createBuilder()
+ .name(Text.translatable("skyblocker.config.quickNav.button", index))
+ .collapsed(true)
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("skyblocker.config.quickNav.button.render"))
+ .binding(defaultButton.render,
+ () -> button.render,
+ newValue -> button.render = newValue)
+ .controller(ConfigUtils::createBooleanController)
.build())
-
- //Button 8
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 8))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button8.render,
- () -> config.quickNav.button8.render,
- newValue -> config.quickNav.button8.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button8.item.id,
- () -> config.quickNav.button8.item.id,
- newValue -> config.quickNav.button8.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button8.item.count,
- () -> config.quickNav.button8.item.count,
- newValue -> config.quickNav.button8.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button8.item.nbt,
- () -> config.quickNav.button8.item.nbt,
- newValue -> config.quickNav.button8.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button8.uiTitle,
- () -> config.quickNav.button8.uiTitle,
- newValue -> config.quickNav.button8.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button8.clickEvent,
- () -> config.quickNav.button8.clickEvent,
- newValue -> config.quickNav.button8.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
+ .option(Option.<Item>createBuilder()
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
+ .binding(defaultButton.itemData.item,
+ () -> button.itemData.item,
+ newValue -> button.itemData.item = newValue)
+ .controller(ItemControllerBuilder::create)
.build())
-
- //Button 9
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 9))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button9.render,
- () -> config.quickNav.button9.render,
- newValue -> config.quickNav.button9.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button9.item.id,
- () -> config.quickNav.button9.item.id,
- newValue -> config.quickNav.button9.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button9.item.count,
- () -> config.quickNav.button9.item.count,
- newValue -> config.quickNav.button9.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button9.item.nbt,
- () -> config.quickNav.button9.item.nbt,
- newValue -> config.quickNav.button9.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button9.uiTitle,
- () -> config.quickNav.button9.uiTitle,
- newValue -> config.quickNav.button9.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button9.clickEvent,
- () -> config.quickNav.button9.clickEvent,
- newValue -> config.quickNav.button9.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
+ .option(Option.<Integer>createBuilder()
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
+ .binding(defaultButton.itemData.count,
+ () -> button.itemData.count,
+ newValue -> button.itemData.count = newValue)
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.build())
-
- //Button 10
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 10))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button10.render,
- () -> config.quickNav.button10.render,
- newValue -> config.quickNav.button10.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button10.item.id,
- () -> config.quickNav.button10.item.id,
- newValue -> config.quickNav.button10.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button10.item.count,
- () -> config.quickNav.button10.item.count,
- newValue -> config.quickNav.button10.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button10.item.nbt,
- () -> config.quickNav.button10.item.nbt,
- newValue -> config.quickNav.button10.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button10.uiTitle,
- () -> config.quickNav.button10.uiTitle,
- newValue -> config.quickNav.button10.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button10.clickEvent,
- () -> config.quickNav.button10.clickEvent,
- newValue -> config.quickNav.button10.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
+ .option(Option.<String>createBuilder()
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaultButton.itemData.components,
+ () -> button.itemData.components,
+ newValue -> button.itemData.components = newValue)
+ .controller(StringControllerBuilder::create)
.build())
-
- //Button 11
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 11))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button11.render,
- () -> config.quickNav.button11.render,
- newValue -> config.quickNav.button11.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button11.item.id,
- () -> config.quickNav.button11.item.id,
- newValue -> config.quickNav.button11.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button11.item.count,
- () -> config.quickNav.button11.item.count,
- newValue -> config.quickNav.button11.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button11.item.nbt,
- () -> config.quickNav.button11.item.nbt,
- newValue -> config.quickNav.button11.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button11.uiTitle,
- () -> config.quickNav.button11.uiTitle,
- newValue -> config.quickNav.button11.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button11.clickEvent,
- () -> config.quickNav.button11.clickEvent,
- newValue -> config.quickNav.button11.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
+ .option(Option.<String>createBuilder()
+ .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
+ .binding(defaultButton.uiTitle,
+ () -> button.uiTitle,
+ newValue -> button.uiTitle = newValue)
+ .controller(StringControllerBuilder::create)
.build())
-
- //Button 12
- .group(OptionGroup.createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button", 12))
- .collapsed(true)
- .option(Option.<Boolean>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.render"))
- .binding(defaults.quickNav.button12.render,
- () -> config.quickNav.button12.render,
- newValue -> config.quickNav.button12.render = newValue)
- .controller(ConfigUtils::createBooleanController)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.itemName"))
- .binding(defaults.quickNav.button12.item.id,
- () -> config.quickNav.button12.item.id,
- newValue -> config.quickNav.button12.item.id = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<Integer>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.count"))
- .binding(defaults.quickNav.button12.item.count,
- () -> config.quickNav.button12.item.count,
- newValue -> config.quickNav.button12.item.count = newValue)
- .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 64))
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.item.nbt"))
- .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.nbt.@Tooltip")))
- .binding(defaults.quickNav.button12.item.nbt,
- () -> config.quickNav.button12.item.nbt,
- newValue -> config.quickNav.button12.item.nbt = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.uiTitle"))
- .binding(defaults.quickNav.button12.uiTitle,
- () -> config.quickNav.button12.uiTitle,
- newValue -> config.quickNav.button12.uiTitle = newValue)
- .controller(StringControllerBuilder::create)
- .build())
- .option(Option.<String>createBuilder()
- .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
- .binding(defaults.quickNav.button12.clickEvent,
- () -> config.quickNav.button12.clickEvent,
- newValue -> config.quickNav.button12.clickEvent = newValue)
- .controller(StringControllerBuilder::create)
- .build())
+ .option(Option.<String>createBuilder()
+ .name(Text.translatable("skyblocker.config.quickNav.button.clickEvent"))
+ .binding(defaultButton.clickEvent,
+ () -> button.clickEvent,
+ newValue -> button.clickEvent = newValue)
+ .controller(StringControllerBuilder::create)
.build())
-
.build();
}
}
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java
index c6936335..369a9a90 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java
@@ -8,12 +8,15 @@ import de.hysky.skyblocker.config.configs.UIAndVisualsConfig;
import de.hysky.skyblocker.utils.waypoint.Waypoint;
import dev.isxander.yacl3.api.ConfigCategory;
import dev.isxander.yacl3.api.*;
+import dev.isxander.yacl3.api.controller.ColorControllerBuilder;
import dev.isxander.yacl3.api.controller.FloatFieldControllerBuilder;
import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
+import java.awt.*;
+
public class UIAndVisualsCategory {
public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig config) {
return ConfigCategory.createBuilder()
@@ -333,6 +336,28 @@ public class UIAndVisualsCategory {
.build())
.build())
+ //Input Calculator
+ .group(OptionGroup.createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.inputCalculator"))
+ .collapsed(true)
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.inputCalculator.enabled"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.uiAndVisuals.inputCalculator.enabled.@Tooltip")))
+ .binding(defaults.uiAndVisuals.inputCalculator.enabled,
+ () -> config.uiAndVisuals.inputCalculator.enabled,
+ newValue -> config.uiAndVisuals.inputCalculator.enabled = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.inputCalculator.requiresEquals"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.uiAndVisuals.inputCalculator.requiresEquals.@Tooltip")))
+ .binding(defaults.uiAndVisuals.inputCalculator.requiresEquals,
+ () -> config.uiAndVisuals.inputCalculator.requiresEquals,
+ newValue -> config.uiAndVisuals.inputCalculator.requiresEquals = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
+ .build())
+
//Flame Overlay
.group(OptionGroup.createBuilder()
.name(Text.translatable("skyblocker.config.uiAndVisuals.flameOverlay"))
@@ -355,6 +380,49 @@ public class UIAndVisualsCategory {
.build())
.build())
+ //Compact Damage Numbers
+ .group(OptionGroup.createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage"))
+ .collapsed(true)
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.enabled"))
+ .binding(defaults.uiAndVisuals.compactDamage.enabled,
+ () -> config.uiAndVisuals.compactDamage.enabled,
+ newValue -> config.uiAndVisuals.compactDamage.enabled = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
+ .option(Option.<Integer>createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.precision"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.precision.@Tooltip")))
+ .binding(defaults.uiAndVisuals.compactDamage.precision,
+ () -> config.uiAndVisuals.compactDamage.precision,
+ newValue -> config.uiAndVisuals.compactDamage.precision = newValue)
+ .controller(opt -> IntegerSliderControllerBuilder.create(opt).range(1,3).step(1))
+ .build())
+ .option(Option.<Color>createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.normalDamageColor"))
+ .binding(defaults.uiAndVisuals.compactDamage.normalDamageColor,
+ () -> config.uiAndVisuals.compactDamage.normalDamageColor,
+ newValue -> config.uiAndVisuals.compactDamage.normalDamageColor = newValue)
+ .controller(ColorControllerBuilder::create)
+ .build())
+ .option(Option.<Color>createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.critDamageGradientStart"))
+ .binding(defaults.uiAndVisuals.compactDamage.critDamageGradientStart,
+ () -> config.uiAndVisuals.compactDamage.critDamageGradientStart,
+ newValue -> config.uiAndVisuals.compactDamage.critDamageGradientStart = newValue)
+ .controller(ColorControllerBuilder::create)
+ .build())
+ .option(Option.<Color>createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.critDamageGradientEnd"))
+ .binding(defaults.uiAndVisuals.compactDamage.critDamageGradientEnd,
+ () -> config.uiAndVisuals.compactDamage.critDamageGradientEnd,
+ newValue -> config.uiAndVisuals.compactDamage.critDamageGradientEnd = newValue)
+ .controller(ColorControllerBuilder::create)
+ .build())
+ .build()
+ )
+
.build();
}
}
diff --git a/src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java
index 2c99dc56..7b394b53 100644
--- a/src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java
@@ -24,6 +24,9 @@ public class DungeonsConfig {
public boolean allowDroppingProtectedItems = false;
@SerialEntry
+ public boolean hideSoulweaverSkulls = false;
+
+ @SerialEntry
public DungeonMap dungeonMap = new DungeonMap();
@SerialEntry
@@ -127,6 +130,9 @@ public class DungeonsConfig {
@SerialEntry
public boolean solveStartsWith = true;
+
+ @SerialEntry
+ public boolean blockIncorrectClicks = false;
}
public static class SecretWaypoints {
diff --git a/src/main/java/de/hysky/skyblocker/config/configs/ForagingConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/ForagingConfig.java
new file mode 100644
index 00000000..1a7c3598
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/config/configs/ForagingConfig.java
@@ -0,0 +1,13 @@
+package de.hysky.skyblocker.config.configs;
+
+import dev.isxander.yacl3.config.v2.api.SerialEntry;
+
+public class ForagingConfig {
+
+ @SerialEntry
+ public Hunting hunting = new Hunting();
+
+ public static class Hunting {
+
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java
index fe845e55..65fd63ca 100644
--- a/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java
@@ -21,6 +21,9 @@ public class MiningConfig {
@SerialEntry
public CrystalsWaypoints crystalsWaypoints = new CrystalsWaypoints();
+ @SerialEntry
+ public CommissionWaypoints commissionWaypoints = new CommissionWaypoints();
+
public static class DwarvenMines {
@SerialEntry
public boolean solveFetchur = true;
@@ -85,6 +88,37 @@ public class MiningConfig {
public boolean findInChat = true;
}
+ public static class CommissionWaypoints {
+ @SerialEntry
+ public CommissionWaypointMode mode = CommissionWaypointMode.BOTH;
+
+ @SerialEntry
+ public boolean useColor = true;
+
+ @SerialEntry
+ public float textScale = 1;
+
+ @SerialEntry
+ public boolean showBaseCamp = false;
+
+ @SerialEntry
+ public boolean showEmissary = true;
+ }
+
+ public enum CommissionWaypointMode {
+ OFF, DWARVEN, GLACITE, BOTH;
+
+ @Override
+ public String toString() {
+ return switch (this) {
+ case OFF -> "Off";
+ case DWARVEN -> "Dwarven";
+ case GLACITE -> "Glacite";
+ case BOTH -> "Both";
+ };
+ }
+ }
+
public enum DwarvenHudStyle {
SIMPLE, FANCY, CLASSIC;
diff --git a/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java
index 2c4347b6..20a0c9cc 100644
--- a/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java
@@ -1,6 +1,9 @@
package de.hysky.skyblocker.config.configs;
import dev.isxander.yacl3.config.v2.api.SerialEntry;
+import net.minecraft.item.Item;
+import net.minecraft.registry.Registries;
+import net.minecraft.util.Identifier;
public class QuickNavigationConfig {
@SerialEntry
@@ -24,14 +27,13 @@ public class QuickNavigationConfig {
* " \\([12]\\/2\\)" : match on the page either " (1/2)" or " (2/2)"
*/
@SerialEntry
- public QuickNavItem button4 = new QuickNavItem(true,
- new ItemData("leather_chestplate", 1, "tag:{display:{color:8991416}}"), "Wardrobe \\([12]/2\\)",
- "/wardrobe");
+ public QuickNavItem button4 = new QuickNavItem(true, new ItemData("leather_chestplate", 1, "[minecraft:dyed_color={rgb:8991416}]"), "Wardrobe \\([12]/2\\)", "/wardrobe");
@SerialEntry
- public QuickNavItem button5 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;-2081424676,-57521078,-2073572414,158072763],Properties:{textures:[{Value:\"ewogICJ0aW1lc3RhbXAiIDogMTU5MTMxMDU4NTYwOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBhMDc3ZTI0OGQxNDI3NzJlYTgwMDg2NGY4YzU3OGI5ZDM2ODg1YjI5ZGFmODM2YjY0YTcwNjg4MmI2ZWMxMCIKICAgIH0KICB9Cn0=\"}]}}}"),
- "Sack of Sacks", "/sacks");
+ public QuickNavItem button5 = new QuickNavItem(true, new ItemData("player_head", 1, "[minecraft:profile={id:[I;-2081424676,-57521078,-2073572414,158072763],name:\"\",properties:[{name:\"textures\",value:\"ewogICJ0aW1lc3RhbXAiIDogMTU5MTMxMDU4NTYwOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBhMDc3ZTI0OGQxNDI3NzJlYTgwMDg2NGY4YzU3OGI5ZDM2ODg1YjI5ZGFmODM2YjY0YTcwNjg4MmI2ZWMxMCIKICAgIH0KICB9Cn0=\"}]}]"), "Sack of Sacks", "/sacks");
+
+ @SerialEntry
+ public QuickNavItem button6 = new QuickNavItem(true, new ItemData("player_head", 1, "[minecraft:profile={name:\"5da6bec64bd942bc\",id:[I;1571208902,1272529596,-1566400349,-679283814],properties:[{name:\"textures\",value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTYxYTkxOGMwYzQ5YmE4ZDA1M2U1MjJjYjkxYWJjNzQ2ODkzNjdiNGQ4YWEwNmJmYzFiYTkxNTQ3MzA5ODVmZiJ9fX0=\"}]}]"), "Accessory Bag(?: \\(\\d/\\d\\))?", "/accessories");
/* REGEX Explanation
* "(?:Rift )?" : optional match on the non-capturing group "Rift "
@@ -39,115 +41,42 @@ public class QuickNavigationConfig {
* "(?: \\([12]\\/2\\))?" : optional match on the non-capturing group " (1/2)" or " (2/2)"
*/
@SerialEntry
- public QuickNavItem button6 = new QuickNavItem(true, new ItemData("ender_chest"),
- "(?:Rift )?Storage(?: \\(1/2\\))?", "/storage");
+ public QuickNavItem button7 = new QuickNavItem(true, new ItemData("ender_chest"), "(?:Rift )?Storage(?: \\(\\d/\\d\\))?", "/storage");
@SerialEntry
- public QuickNavItem button7 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}"),
- "none", "/hub");
+ public QuickNavItem button8 = new QuickNavItem(true, new ItemData("player_head", 1, "[minecraft:profile={name:\"421a8ef40eff47f4\",id:[I;1109036788,251611124,-2126904485,-130621758],properties:[{name:\"textures\",value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzljODg4MWU0MjkxNWE5ZDI5YmI2MWExNmZiMjZkMDU5OTEzMjA0ZDI2NWRmNWI0MzliM2Q3OTJhY2Q1NiJ9fX0=\"}]}]"), "", "/is");
@SerialEntry
- public QuickNavItem button8 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;1605800870,415127827,-1236127084,15358548],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}}}"),
- "none", "/warp dungeon_hub");
+ public QuickNavItem button9 = new QuickNavItem(true, new ItemData("player_head", 1, "[minecraft:profile={name:\"e30e30d02878417c\",id:[I;-485609264,678969724,-1929747597,-718202427],properties:[{name:\"textures\",value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjQ4ODBkMmMxZTdiODZlODc1MjJlMjA4ODI2NTZmNDViYWZkNDJmOTQ5MzJiMmM1ZTBkNmVjYWE0OTBjYjRjIn19fQ==\"}]}]"), "", "/warp garden");
@SerialEntry
- public QuickNavItem button9 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;-562285948,532499670,-1705302742,775653035],Properties:{textures:[{Value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjVkZjU1NTkyNjQzMGQ1ZDc1YWRlZDIxZGQ5NjE5Yjc2YzViN2NhMmM3ZjU0MDE0NDA1MjNkNTNhOGJjZmFhYiJ9fX0=\"}]}}}"),
- "Visit prtl", "/visit prtl");
+ public QuickNavItem button10 = new QuickNavItem(true, new ItemData("player_head", 1, "[minecraft:profile={id:[I;-300151517,-631415889,-1193921967,-1821784279],name:\"\",properties:[{name:\"textures\",value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}]"), "none", "/hub");
@SerialEntry
- public QuickNavItem button10 = new QuickNavItem(true, new ItemData("enchanting_table"), "Enchant Item",
- "/etable");
-
+ public QuickNavItem button11 = new QuickNavItem(true, new ItemData("player_head", 1, "[minecraft:profile={id:[I;1605800870,415127827,-1236127084,15358548],name:\"\",properties:[{name:\"textures\",value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}]"), "none", "/warp dungeon_hub");
@SerialEntry
- public QuickNavItem button11 = new QuickNavItem(true, new ItemData("anvil"), "Anvil", "/anvil");
+ public QuickNavItem button12 = new QuickNavItem(true, new ItemData("gold_block"), "", "/ah");
@SerialEntry
- public QuickNavItem button12 = new QuickNavItem(true, new ItemData("crafting_table"), "Craft Item", "/craft");
-
- public static class QuickNav {
- @SerialEntry
- public boolean enableQuickNav = true;
-
- @SerialEntry
- public QuickNavItem button1 = new QuickNavItem(true, new ItemData("diamond_sword"), "Your Skills", "/skills");
-
- @SerialEntry
- public QuickNavItem button2 = new QuickNavItem(true, new ItemData("painting"), "Collections", "/collection");
-
- /* REGEX Explanation
- * "Pets" : simple match on letters
- * "(?: \\(\\d+\\/\\d+\\))?" : optional match on the non-capturing group for the page in the format " ($number/$number)"
- */
- @SerialEntry
- public QuickNavItem button3 = new QuickNavItem(true, new ItemData("bone"), "Pets(:? \\(\\d+\\/\\d+\\))?", "/pets");
-
- /* REGEX Explanation
- * "Wardrobe" : simple match on letters
- * " \\([12]\\/2\\)" : match on the page either " (1/2)" or " (2/2)"
- */
- @SerialEntry
- public QuickNavItem button4 = new QuickNavItem(true,
- new ItemData("leather_chestplate", 1, "tag:{display:{color:8991416}}"), "Wardrobe \\([12]/2\\)",
- "/wardrobe");
-
- @SerialEntry
- public QuickNavItem button5 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;-2081424676,-57521078,-2073572414,158072763],Properties:{textures:[{Value:\"ewogICJ0aW1lc3RhbXAiIDogMTU5MTMxMDU4NTYwOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBhMDc3ZTI0OGQxNDI3NzJlYTgwMDg2NGY4YzU3OGI5ZDM2ODg1YjI5ZGFmODM2YjY0YTcwNjg4MmI2ZWMxMCIKICAgIH0KICB9Cn0=\"}]}}}"),
- "Sack of Sacks", "/sacks");
-
- /* REGEX Explanation
- * "(?:Rift )?" : optional match on the non-capturing group "Rift "
- * "Storage" : simple match on letters
- * "(?: \\([12]\\/2\\))?" : optional match on the non-capturing group " (1/2)" or " (2/2)"
- */
- @SerialEntry
- public QuickNavItem button6 = new QuickNavItem(true, new ItemData("ender_chest"),
- "(?:Rift )?Storage(?: \\(1/2\\))?", "/storage");
-
- @SerialEntry
- public QuickNavItem button7 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}"),
- "none", "/hub");
+ public QuickNavItem button13 = new QuickNavItem(true, new ItemData("player_head", 1, "[minecraft:profile={id:[I;-562285948,532499670,-1705302742,775653035],name:\"\",properties:[{name:\"textures\",value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmZlMmRjZGE0MWVjM2FmZjhhZjUwZjI3MmVjMmUwNmE4ZjUwOWUwZjgwN2YyMzU1YTFmNWEzM2MxYjY2ZTliNCJ9fX0=\"}]}]"), "Bazaar .*", "/bz");
- @SerialEntry
- public QuickNavItem button8 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;1605800870,415127827,-1236127084,15358548],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}}}"),
- "none", "/warp dungeon_hub");
-
- @SerialEntry
- public QuickNavItem button9 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;-562285948,532499670,-1705302742,775653035],Properties:{textures:[{Value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjVkZjU1NTkyNjQzMGQ1ZDc1YWRlZDIxZGQ5NjE5Yjc2YzViN2NhMmM3ZjU0MDE0NDA1MjNkNTNhOGJjZmFhYiJ9fX0=\"}]}}}"),
- "Visit prtl", "/visit prtl");
-
- @SerialEntry
- public QuickNavItem button10 = new QuickNavItem(true, new ItemData("enchanting_table"), "Enchant Item",
- "/etable");
-
-
- @SerialEntry
- public QuickNavItem button11 = new QuickNavItem(true, new ItemData("anvil"), "Anvil", "/anvil");
-
- @SerialEntry
- public QuickNavItem button12 = new QuickNavItem(true, new ItemData("crafting_table"), "Craft Item", "/craft");
- }
+ @SerialEntry
+ public QuickNavItem button14 = new QuickNavItem(true, new ItemData("crafting_table"), "Craft Item", "/craft");
public static class QuickNavItem {
public QuickNavItem(Boolean render, ItemData itemData, String uiTitle, String clickEvent) {
this.render = render;
- this.item = itemData;
+ this.itemData = itemData;
this.clickEvent = clickEvent;
this.uiTitle = uiTitle;
}
@SerialEntry
- public Boolean render;
+ public boolean render;
@SerialEntry
- public ItemData item;
+ public ItemData itemData;
@SerialEntry
public String uiTitle;
@@ -157,25 +86,31 @@ public class QuickNavigationConfig {
}
public static class ItemData {
- public ItemData(String id, int count, String nbt) {
- this.id = id;
- this.count = count;
- this.nbt = nbt;
+ public ItemData(String item) {
+ this(item, 1, "[]");
}
- public ItemData(String id) {
- this.id = id;
- this.count = 1;
- this.nbt = "";
+ public ItemData(String item, int count, String components) {
+ this(Registries.ITEM.get(new Identifier(item)), count, components);
+ }
+
+ public ItemData(Item item) {
+ this(item, 1, "[]");
+ }
+
+ public ItemData(Item item, int count, String components) {
+ this.item = item;
+ this.count = count;
+ this.components = components;
}
@SerialEntry
- public String id;
+ public Item item;
@SerialEntry
public int count;
@SerialEntry
- public String nbt;
+ public String components;
}
}
diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java
index 267dde14..e016988b 100644
--- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java
@@ -4,6 +4,7 @@ import de.hysky.skyblocker.utils.waypoint.Waypoint;
import dev.isxander.yacl3.config.v2.api.SerialEntry;
import net.minecraft.util.Formatting;
+import java.awt.*;
import java.util.ArrayList;
import java.util.List;
@@ -54,8 +55,14 @@ public class UIAndVisualsConfig {
public SearchOverlay searchOverlay = new SearchOverlay();
@SerialEntry
+ public InputCalculator inputCalculator = new InputCalculator();
+
+ @SerialEntry
public FlameOverlay flameOverlay = new FlameOverlay();
+ @SerialEntry
+ public CompactDamage compactDamage = new CompactDamage();
+
public static class ChestValue {
@SerialEntry
public boolean enableChestValue = true;
@@ -239,6 +246,14 @@ public class UIAndVisualsConfig {
public List<String> auctionHistory = new ArrayList<>();
}
+ public static class InputCalculator {
+ @SerialEntry
+ public boolean enabled = true;
+
+ @SerialEntry
+ public boolean requiresEquals = false;
+ }
+
public static class FlameOverlay {
@SerialEntry
public int flameHeight = 100;
@@ -247,4 +262,20 @@ public class UIAndVisualsConfig {
public int flameOpacity = 100;
}
+ public static class CompactDamage {
+ @SerialEntry
+ public boolean enabled = true;
+
+ @SerialEntry
+ public int precision = 1;
+
+ @SerialEntry
+ public Color normalDamageColor = new Color(0xFFFFFF);
+
+ @SerialEntry
+ public Color critDamageGradientStart = new Color(0xFFFF55);
+
+ @SerialEntry
+ public Color critDamageGradientEnd = new Color(0xFF5555);
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFix.java b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFix.java
new file mode 100644
index 00000000..9ec0e2b8
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFix.java
@@ -0,0 +1,16 @@
+package de.hysky.skyblocker.config.datafixer;
+
+import com.mojang.datafixers.DataFix;
+import com.mojang.datafixers.DataFixUtils;
+import com.mojang.datafixers.schemas.Schema;
+import com.mojang.serialization.Dynamic;
+
+public abstract class ConfigDataFix extends DataFix {
+ public ConfigDataFix(Schema outputSchema, boolean changesType) {
+ super(outputSchema, changesType);
+ }
+
+ protected <T> Dynamic<T> fixVersion(Dynamic<T> dynamic) {
+ return dynamic.set("version", dynamic.createInt(DataFixUtils.getVersion(getVersionKey())));
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixer.java b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixer.java
new file mode 100644
index 00000000..f4e4aad1
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixer.java
@@ -0,0 +1,96 @@
+package de.hysky.skyblocker.config.datafixer;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.mojang.datafixers.DSL;
+import com.mojang.datafixers.DataFixer;
+import com.mojang.datafixers.DataFixerBuilder;
+import com.mojang.datafixers.schemas.Schema;
+import com.mojang.logging.LogUtils;
+import com.mojang.serialization.Dynamic;
+import com.mojang.serialization.JsonOps;
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.datafixer.JsonHelper;
+import net.fabricmc.loader.api.FabricLoader;
+import org.slf4j.Logger;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class ConfigDataFixer {
+ protected static final Logger LOGGER = LogUtils.getLogger();
+ private static final Path CONFIG_DIR = FabricLoader.getInstance().getConfigDir();
+ public static final DSL.TypeReference CONFIG_TYPE = () -> "config";
+
+ public static void apply() {
+ apply(CONFIG_DIR.resolve("skyblocker.json"), CONFIG_DIR.resolve("skyblocker.json.old"));
+ }
+
+ public static void apply(Path configDir, Path backupDir) {
+ //User is new - has no config file (or maybe config folder)
+ if (!Files.exists(CONFIG_DIR) || !Files.exists(configDir)) return;
+
+ //Should never be null if the file exists unless its malformed JSON or something in which case well it gets reset
+ JsonObject oldConfig = loadConfig(configDir);
+ if (oldConfig == null || JsonHelper.getInt(oldConfig, "version").orElse(1) == SkyblockerConfigManager.CONFIG_VERSION) return;
+
+ JsonObject newConfig = apply(oldConfig);
+
+ //Write the updated file
+ if (!writeConfig(configDir, newConfig)) {
+ LOGGER.error(LogUtils.FATAL_MARKER, "[Skyblocker Config Data Fixer] Failed to fix up config file!");
+ writeConfig(backupDir, oldConfig);
+ }
+ }
+
+ public static JsonObject apply(JsonObject oldConfig) {
+ return apply(oldConfig, SkyblockerConfigManager.CONFIG_VERSION);
+ }
+
+ public static JsonObject apply(JsonObject oldConfig, int newVersion) {
+ long start = System.currentTimeMillis();
+
+ JsonObject newConfig = build().update(CONFIG_TYPE, new Dynamic<>(JsonOps.INSTANCE, oldConfig), JsonHelper.getInt(oldConfig, "version").orElse(1), newVersion).getValue().getAsJsonObject();
+
+ long end = System.currentTimeMillis();
+ LOGGER.info("[Skyblocker Config Data Fixer] Applied datafixers in {} ms!", end - start);
+ return newConfig;
+ }
+
+ private static DataFixer build() {
+ DataFixerBuilder builder = new DataFixerBuilder(SkyblockerConfigManager.CONFIG_VERSION);
+
+ builder.addSchema(1, ConfigSchema::new);
+ Schema schema2 = builder.addSchema(2, Schema::new);
+ builder.addFixer(new ConfigFix1(schema2, true));
+ Schema schema3 = builder.addSchema(3, Schema::new);
+ builder.addFixer(new ConfigFix2QuickNav(schema3, true));
+
+ return builder.buildUnoptimized();
+ }
+
+ private static JsonObject loadConfig(Path path) {
+ try (BufferedReader reader = Files.newBufferedReader(path)) {
+ return JsonParser.parseReader(reader).getAsJsonObject();
+ } catch (Throwable t) {
+ LOGGER.error("[Skyblocker Config Data Fixer] Failed to load config file!", t);
+ }
+
+ return null;
+ }
+
+ private static boolean writeConfig(Path path, JsonObject config) {
+ try (BufferedWriter writer = Files.newBufferedWriter(path)) {
+ SkyblockerMod.GSON.toJson(config, writer);
+
+ return true;
+ } catch (Throwable t) {
+ LOGGER.error("[Skyblocker Config Data Fixer] Failed to save config file at {}!", path, t);
+ }
+
+ return false;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix1.java b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix1.java
new file mode 100644
index 00000000..8eff09e7
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix1.java
@@ -0,0 +1,211 @@
+package de.hysky.skyblocker.config.datafixer;
+
+import com.mojang.datafixers.DSL;
+import com.mojang.datafixers.TypeRewriteRule;
+import com.mojang.datafixers.schemas.Schema;
+import com.mojang.logging.LogUtils;
+import com.mojang.serialization.Dynamic;
+import com.mojang.serialization.OptionalDynamic;
+import de.hysky.skyblocker.utils.datafixer.ItemStackComponentizationFixer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.StringNbtReader;
+
+import java.util.Locale;
+
+public class ConfigFix1 extends ConfigDataFix {
+ public ConfigFix1(Schema outputSchema, boolean changesType) {
+ super(outputSchema, changesType);
+ }
+
+ @Override
+ protected TypeRewriteRule makeRule() {
+ return fixTypeEverywhereTyped(
+ "ConfigFix1",
+ getInputSchema().getType(ConfigDataFixer.CONFIG_TYPE),
+ typed -> typed.update(DSL.remainderFinder(), this::fix)
+ );
+ }
+
+ private <T> Dynamic<T> fix(Dynamic<T> dynamic) {
+ return fixMisc(fixQuickNav(fixChat(fixSlayers(fixOtherLocations(fixFarming(fixMining(fixCrimsonIsle(fixDungeons(fixHelpers(fixUIAndVisuals(fixGeneral(fixVersion(dynamic)))))))))))));
+ }
+
+ private static <T> Dynamic<T> fixGeneral(Dynamic<T> dynamic) {
+ return dynamic.update("general", general -> general.update("itemTooltip", itemTooltip -> itemTooltip.setFieldIfPresent("dungeonQuality", general.get("dungeonQuality").result())).remove("dungeonQuality"));
+ }
+
+ private static <T> Dynamic<T> fixUIAndVisuals(Dynamic<T> dynamic) {
+ OptionalDynamic<T> general = dynamic.get("general");
+ return dynamic.set("uiAndVisuals", dynamic.emptyMap()
+ .setFieldIfPresent("compactorDeletorPreview", general.get("compactorDeletorPreview").result())
+ .setFieldIfPresent("dontStripSkinAlphaValues", general.get("dontStripSkinAlphaValues").result())
+ .setFieldIfPresent("backpackPreviewWithoutShift", general.get("backpackPreviewWithoutShift").result())
+ .setFieldIfPresent("hideEmptyTooltips", general.get("hideEmptyTooltips").result())
+ .setFieldIfPresent("fancyCraftingTable", general.get("fancyCraftingTable").result())
+ .setFieldIfPresent("hideStatusEffectOverlay", general.get("hideStatusEffectOverlay").result())
+ .setFieldIfPresent("chestValue", general.get("chestValue").result())
+ .setFieldIfPresent("itemCooldown", general.get("itemCooldown").result())
+ .setFieldIfPresent("titleContainer", general.get("titleContainer").result())
+ .setFieldIfPresent("tabHud", general.get("tabHud").result())
+ .setFieldIfPresent("fancyAuctionHouse", general.get("fancyAuctionHouse").result())
+ .setFieldIfPresent("bars", general.get("bars").result())
+ .setFieldIfPresent("waypoints", general.get("waypoints").result())
+ .setFieldIfPresent("teleportOverlay", general.get("teleportOverlay").result())
+ .setFieldIfPresent("searchOverlay", general.get("searchOverlay").result())
+ .setFieldIfPresent("flameOverlay", general.get("flameOverlay").result())
+ ).update("general", newGeneral -> newGeneral
+ .remove("compactorDeletorPreview")
+ .remove("dontStripSkinAlphaValues")
+ .remove("backpackPreviewWithoutShift")
+ .remove("hideEmptyTooltips")
+ .remove("fancyCraftingTable")
+ .remove("hideStatusEffectOverlay")
+ .remove("chestValue")
+ .remove("itemCooldown")
+ .remove("titleContainer")
+ .remove("tabHud")
+ .remove("fancyAuctionHouse")
+ .remove("bars")
+ .remove("waypoints")
+ .remove("teleportOverlay")
+ .remove("searchOverlay")
+ .remove("flameOverlay")
+ );
+ }
+
+ private static <T> Dynamic<T> fixHelpers(Dynamic<T> dynamic) {
+ OptionalDynamic<T> general = dynamic.get("general");
+ return dynamic.set("helpers", dynamic.emptyMap()
+ .setFieldIfPresent("enableNewYearCakesHelper", general.get("enableNewYearCakesHelper").result())
+ .setFieldIfPresent("mythologicalRitual", general.get("mythologicalRitual").result())
+ .setFieldIfPresent("experiments", general.get("experiments").result())
+ .setFieldIfPresent("fishing", general.get("fishing").result())
+ .setFieldIfPresent("fairySouls", general.get("fairySouls").result())
+ ).update("general", newGeneral -> newGeneral
+ .remove("enableNewYearCakesHelper")
+ .remove("mythologicalRitual")
+ .remove("experiments")
+ .remove("fishing")
+ .remove("fairySouls")
+ );
+ }
+
+ private static <T> Dynamic<T> fixDungeons(Dynamic<T> dynamic) {
+ OptionalDynamic<T> general = dynamic.get("general");
+ OptionalDynamic<T> dungeons = dynamic.get("locations").get("dungeons");
+ return dynamic.set("dungeons", dynamic.emptyMap()
+ .setFieldIfPresent("fancyPartyFinder", general.get("betterPartyFinder").result())
+ .setFieldIfPresent("croesusHelper", dungeons.get("croesusHelper").result())
+ .setFieldIfPresent("playerSecretsTracker", dungeons.get("playerSecretsTracker").result())
+ .setFieldIfPresent("starredMobGlow", dungeons.get("starredMobGlow").result())
+ .setFieldIfPresent("starredMobBoundingBoxes", dungeons.get("starredMobBoundingBoxes").result())
+ .setFieldIfPresent("allowDroppingProtectedItems", dungeons.get("allowDroppingProtectedItems").result())
+ .set("dungeonMap", dynamic.emptyMap()
+ .setFieldIfPresent("enableMap", dungeons.get("enableMap").result())
+ .setFieldIfPresent("mapScaling", dungeons.get("mapScaling").result())
+ .setFieldIfPresent("mapX", dungeons.get("mapX").result())
+ .setFieldIfPresent("mapY", dungeons.get("mapY").result())
+ )
+ .set("puzzleSolvers", dynamic.emptyMap()
+ .setFieldIfPresent("solveThreeWeirdos", dungeons.get("solveThreeWeirdos").result())
+ .setFieldIfPresent("blazeSolver", dungeons.get("blazeSolver").result())
+ .setFieldIfPresent("creeperSolver", dungeons.get("creeperSolver").result())
+ .setFieldIfPresent("solveTrivia", dungeons.get("solveTrivia").result())
+ .setFieldIfPresent("solveTicTacToe", dungeons.get("solveTicTacToe").result())
+ .setFieldIfPresent("solveWaterboard", dungeons.get("solveWaterboard").result())
+ .setFieldIfPresent("solveBoulder", dungeons.get("solveBoulder").result())
+ .setFieldIfPresent("solveIceFill", dungeons.get("solveIceFill").result())
+ .setFieldIfPresent("solveSilverfish", dungeons.get("solveSilverfish").result())
+ )
+ .set("theProfessor", dynamic.emptyMap()
+ .setFieldIfPresent("fireFreezeStaffTimer", dungeons.get("fireFreezeStaffTimer").result())
+ .setFieldIfPresent("floor3GuardianHealthDisplay", dungeons.get("floor3GuardianHealthDisplay").result())
+ )
+ .setFieldIfPresent("livid", dungeons.get("lividColor").result())
+ .setFieldIfPresent("terminals", dungeons.get("terminals").result())
+ .setFieldIfPresent("secretWaypoints", dungeons.get("secretWaypoints").result())
+ .setFieldIfPresent("mimicMessage", dungeons.get("mimicMessage").result())
+ .setFieldIfPresent("doorHighlight", dungeons.get("doorHighlight").result())
+ .setFieldIfPresent("dungeonScore", dungeons.get("dungeonScore").result())
+ .setFieldIfPresent("dungeonChestProfit", dungeons.get("dungeonChestProfit").result())
+ ).update("locations", locations -> locations.remove("dungeons")).update("general", newGeneral -> newGeneral.remove("betterPartyFinder"));
+ }
+
+ private static <T> Dynamic<T> fixCrimsonIsle(Dynamic<T> dynamic) {
+ return dynamic.setFieldIfPresent("crimsonIsle", dynamic.get("locations").get("crimsonIsle").result()).update("locations", locations -> locations.remove("crimsonIsle"));
+ }
+
+ private static <T> Dynamic<T> fixMining(Dynamic<T> dynamic) {
+ OptionalDynamic<T> dwarvenMines = dynamic.get("locations").get("dwarvenMines");
+ return dynamic.set("mining", dynamic.emptyMap()
+ .setFieldIfPresent("enableDrillFuel", dwarvenMines.get("enableDrillFuel").result())
+ .set("dwarvenMines", dynamic.emptyMap()
+ .setFieldIfPresent("solveFetchur", dwarvenMines.get("solveFetchur").result())
+ .setFieldIfPresent("solvePuzzler", dwarvenMines.get("solvePuzzler").result())
+ )
+ .set("dwarvenHud", dwarvenMines.get("dwarvenHud").result().orElseThrow()
+ .renameField("x", "commissionsX")
+ .renameField("y", "commissionsY")
+ )
+ .setFieldIfPresent("crystalsHud", dwarvenMines.get("crystalsHud").result())
+ .setFieldIfPresent("crystalsWaypoints", dwarvenMines.get("crystalsWaypoints").result())
+ .set("crystalHollows", dynamic.emptyMap()
+ .setFieldIfPresent("metalDetectorHelper", dwarvenMines.get("metalDetectorHelper").result())
+ )
+ ).update("locations", locations -> locations.remove("dwarvenMines"));
+ }
+
+ private static <T> Dynamic<T> fixFarming(Dynamic<T> dynamic) {
+ return dynamic.set("farming", dynamic.emptyMap()
+ .setFieldIfPresent("garden", dynamic.get("locations").get("garden").result())
+ ).update("locations", locations -> locations.remove("garden"));
+ }
+
+ private static <T> Dynamic<T> fixOtherLocations(Dynamic<T> dynamic) {
+ return dynamic.renameField("locations", "otherLocations");
+ }
+
+ private static <T> Dynamic<T> fixSlayers(Dynamic<T> dynamic) {
+ return dynamic.renameField("slayer", "slayers");
+ }
+
+ private static <T> Dynamic<T> fixChat(Dynamic<T> dynamic) {
+ return dynamic.renameField("messages", "chat");
+ }
+
+ private static <T> Dynamic<T> fixQuickNav(Dynamic<T> dynamic) {
+ return dynamic.update("quickNav", quickNav -> quickNav.updateMapValues(button ->
+ button.getFirst().asString().getOrThrow().startsWith("button") ? button.mapSecond(ConfigFix1::fixQuickNavButton) : button
+ ));
+ }
+
+ private static <T> Dynamic<T> fixQuickNavButton(Dynamic<T> button) {
+ return button.update("item", item -> item
+ .renameField("itemName", "id")
+ .renameAndFixField("nbt", "components", nbt -> fixNbt(item.get("itemName"), nbt))
+ );
+ }
+
+ private static Dynamic<?> fixNbt(OptionalDynamic<?> id, Dynamic<?> nbt) {
+ try {
+ String itemNbt = "{id:\"minecraft:" + id.asString().getOrThrow().toLowerCase(Locale.ROOT) + "\",Count:1";
+ String extraNbt = nbt.asString().getOrThrow();
+ if (extraNbt.length() > 2) itemNbt += "," + extraNbt;
+ itemNbt += "}";
+
+ ItemStack fixed = ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse(itemNbt));
+
+ return nbt.createString(ItemStackComponentizationFixer.componentsAsString(fixed));
+ } catch (Exception e) {
+ ConfigDataFixer.LOGGER.error(LogUtils.FATAL_MARKER, "[Skyblocker Config Data Fixer] Failed to convert nbt to components!", e);
+ }
+
+ return nbt.createString("[]");
+ }
+
+ private static <T> Dynamic<T> fixMisc(Dynamic<T> dynamic) {
+ return dynamic.set("misc", dynamic.emptyMap()
+ .setFieldIfPresent("richPresence", dynamic.get("richPresence").result())
+ ).remove("richPresence");
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix2QuickNav.java b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix2QuickNav.java
new file mode 100644
index 00000000..bd67b1b0
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix2QuickNav.java
@@ -0,0 +1,38 @@
+package de.hysky.skyblocker.config.datafixer;
+
+import com.mojang.datafixers.DSL;
+import com.mojang.datafixers.TypeRewriteRule;
+import com.mojang.datafixers.schemas.Schema;
+import com.mojang.serialization.Dynamic;
+import net.minecraft.util.Identifier;
+
+public class ConfigFix2QuickNav extends ConfigDataFix {
+ public ConfigFix2QuickNav(Schema outputSchema, boolean changesType) {
+ super(outputSchema, changesType);
+ }
+
+ @Override
+ protected TypeRewriteRule makeRule() {
+ return fixTypeEverywhereTyped(
+ "ConfigFix2QuickNav",
+ getInputSchema().getType(ConfigDataFixer.CONFIG_TYPE),
+ typed -> typed.update(DSL.remainderFinder(), this::fix)
+ );
+ }
+
+ private <T> Dynamic<T> fix(Dynamic<T> dynamic) {
+ return fixVersion(dynamic).update("quickNav", quickNav -> quickNav
+ .renameField("button12", "button13")
+ .renameField("button11", "button12")
+ .renameField("button10", "button11")
+ .renameField("button9", "button10")
+ .renameField("button8", "button9")
+ .renameField("button7", "button8")
+ .updateMapValues(button -> button.getFirst().asString().getOrThrow().startsWith("button") ? button.mapSecond(this::fixButton) : button)
+ );
+ }
+
+ private <T> Dynamic<T> fixButton(Dynamic<T> button) {
+ return button.renameAndFixField("item", "itemData", itemData -> itemData.renameAndFixField("id", "item", id -> id.createString(new Identifier(id.asString().getOrThrow()).toString())));
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigSchema.java b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigSchema.java
new file mode 100644
index 00000000..4c821169
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigSchema.java
@@ -0,0 +1,29 @@
+package de.hysky.skyblocker.config.datafixer;
+
+import com.mojang.datafixers.DSL;
+import com.mojang.datafixers.schemas.Schema;
+import com.mojang.datafixers.types.templates.TypeTemplate;
+
+import java.util.Map;
+import java.util.function.Supplier;
+
+public class ConfigSchema extends Schema {
+ public ConfigSchema(int versionKey, Schema parent) {
+ super(versionKey, parent);
+ }
+
+ @Override
+ public void registerTypes(Schema schema, Map<String, Supplier<TypeTemplate>> entityTypes, Map<String, Supplier<TypeTemplate>> blockEntityTypes) {
+ schema.registerType(true, ConfigDataFixer.CONFIG_TYPE, DSL::remainder);
+ }
+
+ @Override
+ public Map<String, Supplier<TypeTemplate>> registerEntities(Schema schema) {
+ return Map.of();
+ }
+
+ @Override
+ public Map<String, Supplier<TypeTemplate>> registerBlockEntities(Schema schema) {
+ return Map.of();
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/debug/Debug.java b/src/main/java/de/hysky/skyblocker/debug/Debug.java
index 8c883b30..d9ac668c 100644
--- a/src/main/java/de/hysky/skyblocker/debug/Debug.java
+++ b/src/main/java/de/hysky/skyblocker/debug/Debug.java
@@ -2,21 +2,27 @@ package de.hysky.skyblocker.debug;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import com.mojang.serialization.JsonOps;
import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.mixins.accessors.HandledScreenAccessor;
import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.ItemUtils;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenKeyboardEvents;
import net.fabricmc.loader.api.FabricLoader;
+import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.text.Text;
-
-import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
+import org.lwjgl.glfw.GLFW;
import java.util.List;
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
+
public class Debug {
private static final boolean DEBUG_ENABLED = Boolean.parseBoolean(System.getProperty("skyblocker.debug", "false"));
@@ -26,6 +32,10 @@ public class Debug {
return DEBUG_ENABLED || FabricLoader.getInstance().isDevelopmentEnvironment();
}
+ public static boolean shouldShowInvisibleArmorStands() {
+ return showInvisibleArmorStands;
+ }
+
public static void init() {
if (debugEnabled()) {
SnapshotDebug.init();
@@ -35,6 +45,15 @@ public class Debug {
.then(toggleShowingInvisibleArmorStands())
.then(dumpArmorStandHeadTextures())
)));
+ ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
+ if (screen instanceof HandledScreen<?> handledScreen) {
+ ScreenKeyboardEvents.afterKeyPress(screen).register((_screen, key, scancode, modifier) -> {
+ if (key == GLFW.GLFW_KEY_U && client.player != null) {
+ client.player.sendMessage(Text.literal("[Skyblocker Debug] Hovered Item: " + SkyblockerMod.GSON_COMPACT.toJson(ItemStack.CODEC.encodeStart(JsonOps.INSTANCE, ((HandledScreenAccessor) handledScreen).getFocusedSlot().getStack()))));
+ }
+ });
+ }
+ });
}
}
@@ -73,8 +92,4 @@ public class Debug {
return Command.SINGLE_SUCCESS;
});
}
-
- public static boolean shouldShowInvisibleArmorStands() {
- return showInvisibleArmorStands;
- }
}
diff --git a/src/main/java/de/hysky/skyblocker/events/SkyblockEvents.java b/src/main/java/de/hysky/skyblocker/events/SkyblockEvents.java
index 303e454f..c268103d 100644
--- a/src/main/java/de/hysky/skyblocker/events/SkyblockEvents.java
+++ b/src/main/java/de/hysky/skyblocker/events/SkyblockEvents.java
@@ -1,5 +1,6 @@
package de.hysky.skyblocker.events;
+import de.hysky.skyblocker.utils.Location;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.event.Event;
@@ -19,6 +20,12 @@ public final class SkyblockEvents {
}
});
+ public static final Event<SkyblockEvents.SkyblockLocationChange> LOCATION_CHANGE = EventFactory.createArrayBacked(SkyblockEvents.SkyblockLocationChange.class, callbacks -> location -> {
+ for (SkyblockEvents.SkyblockLocationChange callback : callbacks) {
+ callback.onSkyblockLocationChange(location);
+ }
+ });
+
@Environment(EnvType.CLIENT)
@FunctionalInterface
public interface SkyblockJoin {
@@ -30,4 +37,10 @@ public final class SkyblockEvents {
public interface SkyblockLeave {
void onSkyblockLeave();
}
+
+ @Environment(EnvType.CLIENT)
+ @FunctionalInterface
+ public interface SkyblockLocationChange {
+ void onSkyblockLocationChange(Location location);
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java
index 0a5ebc64..2c2c1376 100644
--- a/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java
+++ b/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java
@@ -3,6 +3,8 @@ package de.hysky.skyblocker.mixins;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.sugar.Local;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.CompactDamage;
import de.hysky.skyblocker.skyblock.FishingHelper;
import de.hysky.skyblocker.skyblock.dungeon.DungeonScore;
import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager;
@@ -18,12 +20,11 @@ import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityStatuses;
import net.minecraft.entity.ItemEntity;
-import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
-import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket;
-import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
-import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket;
+import net.minecraft.entity.decoration.ArmorStandEntity;
+import net.minecraft.network.packet.s2c.play.*;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
+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;
@@ -36,6 +37,10 @@ public abstract class ClientPlayNetworkHandlerMixin {
@Shadow
private ClientWorld world;
+ @Shadow
+ @Final
+ private static Logger LOGGER;
+
@Inject(method = "onBlockUpdate", at = @At("RETURN"))
private void skyblocker$onBlockUpdate(BlockUpdateS2CPacket packet, CallbackInfo ci) {
if (Utils.isInTheEnd() && SlayerUtils.isInSlayer()) {
@@ -103,4 +108,14 @@ public abstract class ClientPlayNetworkHandlerMixin {
}
return entity;
}
+
+ @Inject(method = "onEntityTrackerUpdate", at = @At("TAIL"))
+ private void skyblocker$onEntityTrackerUpdate(EntityTrackerUpdateS2CPacket packet, CallbackInfo ci, @Local Entity entity) {
+ if (!SkyblockerConfigManager.get().uiAndVisuals.compactDamage.enabled || !(entity instanceof ArmorStandEntity armorStandEntity)) return;
+ try { //Prevent packet handling fails if something goes wrong so that entity trackers still update, just without compact damage numbers
+ CompactDamage.compactDamage(armorStandEntity);
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker Compact Damage] Failed to compact damage number", e);
+ }
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java b/src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java
index 79d13068..c03a3a55 100644
--- a/src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java
+++ b/src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java
@@ -1,18 +1,34 @@
package de.hysky.skyblocker.mixins;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import com.llamalad7.mixinextras.injector.ModifyReturnValue;
+import com.llamalad7.mixinextras.sugar.Local;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.debug.Debug;
+import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.entity.Entity;
+import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.decoration.ArmorStandEntity;
+
import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(EntityRenderDispatcher.class)
public class EntityRenderDispatcherMixin {
- @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;isInvisible()Z", ordinal = 1))
- private <E extends Entity> boolean skyblocker$armorStandHitboxVisible(boolean invisible, E entity) {
- return (!(entity instanceof ArmorStandEntity) || !Utils.isOnHypixel() || !Debug.debugEnabled() || !Debug.shouldShowInvisibleArmorStands()) && invisible;
- }
+ @Unique
+ private static final String SOULWEAVER_SKULL_TEXTURE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmYyNGVkNjg3NTMwNGZhNGExZjBjNzg1YjJjYjZhNmE3MjU2M2U5ZjNlMjRlYTU1ZTE4MTc4NDUyMTE5YWE2NiJ9fX0=";
+
+ @ModifyReturnValue(method = "shouldRender", at = @At("RETURN"))
+ private <E extends Entity> boolean skyblocker$dontRenderSoulweaverSkulls(boolean original, @Local(argsOnly = true) E entity) {
+ return Utils.isInDungeons() && SkyblockerConfigManager.get().dungeons.hideSoulweaverSkulls && entity instanceof ArmorStandEntity armorStand && entity.isInvisible() && armorStand.hasStackEquipped(EquipmentSlot.HEAD) ? !ItemUtils.getHeadTexture(armorStand.getEquippedStack(EquipmentSlot.HEAD)).equals(SOULWEAVER_SKULL_TEXTURE) : original;
+ }
+
+ @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;isInvisible()Z", ordinal = 1))
+ private <E extends Entity> boolean skyblocker$armorStandHitboxVisible(boolean invisible, E entity) {
+ return (!(entity instanceof ArmorStandEntity) || !Utils.isOnHypixel() || !Debug.debugEnabled() || !Debug.shouldShowInvisibleArmorStands()) && invisible;
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java
index 04e6749c..f662be7c 100644
--- a/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java
+++ b/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java
@@ -14,6 +14,8 @@ import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds;
import de.hysky.skyblocker.skyblock.item.WikiLookup;
import de.hysky.skyblocker.skyblock.item.tooltip.BackpackPreview;
import de.hysky.skyblocker.skyblock.item.tooltip.CompactorDeletorPreview;
+import de.hysky.skyblocker.skyblock.quicknav.QuickNav;
+import de.hysky.skyblocker.skyblock.quicknav.QuickNavButton;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.render.gui.ContainerSolver;
@@ -41,6 +43,7 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
@@ -89,10 +92,22 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
@Final
protected T handler;
+ @Unique
+ private List<QuickNavButton> quickNavButtons;
+
protected HandledScreenMixin(Text title) {
super(title);
}
+ @Inject(method = "init", at = @At("RETURN"))
+ private void skyblocker$initQuickNav(CallbackInfo ci) {
+ if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().quickNav.enableQuickNav && client != null && client.player != null && !client.player.isCreative()) {
+ for (QuickNavButton quickNavButton : quickNavButtons = QuickNav.init(getTitle().getString().trim())) {
+ addSelectableChild(quickNavButton);
+ }
+ }
+ }
+
@Inject(at = @At("HEAD"), method = "keyPressed")
public void skyblocker$keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable<Boolean> cir) {
if (this.client != null && this.focusedSlot != null && keyCode != 256) {
@@ -109,8 +124,33 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
@Inject(at = @At("HEAD"), method = "mouseClicked")
public void skyblocker$mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> cir) {
- if (SkyblockerConfigManager.get().farming.garden.visitorHelper && (Utils.getLocationRaw().equals("garden") && !getTitle().getString().contains("Logbook") || getTitle().getString().startsWith("Bazaar")))
+ if (SkyblockerConfigManager.get().farming.garden.visitorHelper && (Utils.getLocationRaw().equals("garden") && !getTitle().getString().contains("Logbook") || getTitle().getString().startsWith("Bazaar"))) {
VisitorHelper.onMouseClicked(mouseX, mouseY, button, this.textRenderer);
+ }
+ }
+
+ /**
+ * Draws the unselected tabs in front of the background blur, but behind the main inventory, similar to creative inventory tabs
+ */
+ @Inject(method = "renderBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawBackground(Lnet/minecraft/client/gui/DrawContext;FII)V"))
+ private void skyblocker$drawUnselectedQuickNavButtons(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
+ if (quickNavButtons != null) for (QuickNavButton quickNavButton : quickNavButtons) {
+ if (!quickNavButton.toggled()) {
+ quickNavButton.render(context, mouseX, mouseY, delta);
+ }
+ }
+ }
+
+ /**
+ * Draws the selected tab in front of the background blur and the main inventory, similar to creative inventory tabs
+ */
+ @Inject(method = "renderBackground", at = @At("RETURN"))
+ private void skyblocker$drawSelectedQuickNavButtons(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
+ if (quickNavButtons != null) for (QuickNavButton quickNavButton : quickNavButtons) {
+ if (quickNavButton.toggled()) {
+ quickNavButton.render(context, mouseX, mouseY, delta);
+ }
+ }
}
@SuppressWarnings("DataFlowIssue")
@@ -165,7 +205,7 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
/**
* The naming of this method in yarn is half true, its mostly to handle slot/item interactions (which are mouse or keyboard clicks)
* For example, using the drop key bind while hovering over an item will invoke this method to drop the players item
- *
+ *
* @implNote This runs before {@link ScreenHandler#onSlotClick(int, int, SlotActionType, net.minecraft.entity.player.PlayerEntity)}
*/
@Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;clickSlot(IIILnet/minecraft/screen/slot/SlotActionType;Lnet/minecraft/entity/player/PlayerEntity;)V"), cancellable = true)
@@ -216,7 +256,9 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
}
if (currentSolver != null) {
- SkyblockerMod.getInstance().containerSolverManager.onSlotClick(slotId, stack);
+ boolean disallowed = SkyblockerMod.getInstance().containerSolverManager.onSlotClick(slotId, stack);
+
+ if (disallowed) ci.cancel();
}
// Experiment Solvers
diff --git a/src/main/java/de/hysky/skyblocker/mixins/SignEditScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/SignEditScreenMixin.java
new file mode 100644
index 00000000..6706db58
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/SignEditScreenMixin.java
@@ -0,0 +1,44 @@
+package de.hysky.skyblocker.mixins;
+
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.calculators.SignCalculator;
+import de.hysky.skyblocker.utils.Utils;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen;
+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.CallbackInfo;
+
+import java.util.Objects;
+
+@Mixin(AbstractSignEditScreen.class)
+public abstract class SignEditScreenMixin {
+ @Shadow
+ @Final
+ private String[] messages;
+
+ @Inject(method = "render", at = @At("HEAD"))
+ private void skyblocker$render(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
+ //if the sign is being used to enter number send it to the sign calculator
+ if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.inputCalculator.enabled && Objects.equals(messages[1], "^^^^^^^^^^^^^^^")) {
+ SignCalculator.renderCalculator(context, messages[0], context.getScaledWindowWidth() / 2, 55);
+ }
+ }
+
+ @Inject(method = "finishEditing", at = @At("HEAD"))
+ private void skyblocker$finishEditing(CallbackInfo ci) {
+ //if the sign is being used to enter number get number from calculator for if maths has been done
+ if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().uiAndVisuals.inputCalculator.enabled && Objects.equals(messages[1], "^^^^^^^^^^^^^^^")) {
+ boolean isPrice = messages[2].contains("price");
+ String value = SignCalculator.getNewValue(isPrice);
+ if (value.length() >= 15) {
+ value = value.substring(0, 15);
+ }
+ messages[0] = value;
+ }
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/accessors/HandledScreenAccessor.java b/src/main/java/de/hysky/skyblocker/mixins/accessors/HandledScreenAccessor.java
index 447031d4..9a2a8311 100644
--- a/src/main/java/de/hysky/skyblocker/mixins/accessors/HandledScreenAccessor.java
+++ b/src/main/java/de/hysky/skyblocker/mixins/accessors/HandledScreenAccessor.java
@@ -2,6 +2,7 @@ package de.hysky.skyblocker.mixins.accessors;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.screen.ScreenHandler;
+import net.minecraft.screen.slot.Slot;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
@@ -23,4 +24,7 @@ public interface HandledScreenAccessor {
@Mutable
@Accessor("handler")
void setHandler(ScreenHandler handler);
+
+ @Accessor("focusedSlot")
+ Slot getFocusedSlot();
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java b/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java
new file mode 100644
index 00000000..2837364b
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java
@@ -0,0 +1,86 @@
+package de.hysky.skyblocker.skyblock;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.item.CustomArmorAnimatedDyes;
+import net.minecraft.entity.decoration.ArmorStandEntity;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import net.minecraft.text.TextColor;
+import net.minecraft.util.Formatting;
+import org.apache.commons.lang3.math.NumberUtils;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+
+public class CompactDamage {
+ private static final Pattern DAMAGE_PATTERN = Pattern.compile("[✧✯]?[\\d,]+[✧✯]?❤?");
+ private CompactDamage() {
+ }
+
+ public static void compactDamage(ArmorStandEntity entity) {
+ if (!entity.isInvisible() || !entity.hasCustomName() || !entity.isCustomNameVisible()) return;
+ Text customName = entity.getCustomName();
+ String customNameStringified = customName.getString();
+ if (!DAMAGE_PATTERN.matcher(customNameStringified).matches()) return;
+ List<Text> siblings = customName.getSiblings();
+ if (siblings.isEmpty()) return;
+
+ MutableText prettierCustomName;
+ if (siblings.size() == 1) { //Non-crit damage
+ Text text = siblings.getFirst();
+ String dmg = text.getString().replace(",", "");
+ if (!NumberUtils.isParsable(dmg)) return; //Sanity check
+ String prettifiedDmg = prettifyDamageNumber(Long.parseLong(dmg));
+ int color;
+ if (text.getStyle().getColor() != null) {
+ if (text.getStyle().getColor() == TextColor.fromFormatting(Formatting.GRAY)) {
+ color = SkyblockerConfigManager.get().uiAndVisuals.compactDamage.normalDamageColor.getRGB() & 0x00FFFFFF;
+ } else color = text.getStyle().getColor().getRgb();
+ } else color = SkyblockerConfigManager.get().uiAndVisuals.compactDamage.normalDamageColor.getRGB() & 0x00FFFFFF;
+ prettierCustomName = Text.literal("").append(Text.literal(prettifiedDmg).setStyle(customName.getStyle()).withColor(color));
+ } else { //Crit damage
+ boolean wasDoubled = customNameStringified.contains("❤"); //Ring of love ability adds a heart to the end of the damage string
+ int entriesToRemove = wasDoubled ? 2 : 1;
+
+ String dmg = siblings.subList(1, siblings.size() - entriesToRemove) //First and last sibling are the crit symbols and maybe heart
+ .stream()
+ .map(Text::getString)
+ .reduce("", String::concat) //Concatenate all the siblings to get the dmg number
+ .replace(",", "");
+
+ if (!NumberUtils.isParsable(dmg)) return; //Sanity check
+ String dmgSymbol = customNameStringified.charAt(0) != '✯' ? "✧" : "✯"; //Mega Crit ability from the Overload enchantment
+ String prettifiedDmg = dmgSymbol + prettifyDamageNumber(Long.parseLong(dmg)) + dmgSymbol;
+ prettierCustomName = Text.literal("");
+ int length = prettifiedDmg.length();
+ for (int i = 0; i < length; i++) {
+ prettierCustomName.append(Text.literal(prettifiedDmg.substring(i, i + 1)).withColor(
+ CustomArmorAnimatedDyes.interpolate(
+ SkyblockerConfigManager.get().uiAndVisuals.compactDamage.critDamageGradientStart.getRGB() & 0x00FFFFFF,
+ SkyblockerConfigManager.get().uiAndVisuals.compactDamage.critDamageGradientEnd.getRGB() & 0x00FFFFFF,
+ i / (length - 1.0)
+ )
+ ));
+ }
+
+ if (wasDoubled) prettierCustomName.append(Text.literal("❤").formatted(Formatting.LIGHT_PURPLE));
+
+ prettierCustomName.setStyle(customName.getStyle());
+ }
+
+ entity.setCustomName(prettierCustomName);
+ }
+
+ private static String prettifyDamageNumber(long damage) {
+ if (damage < 1_000) return String.valueOf(damage);
+ if (damage < 1_000_000) return format(damage / 1_000.0) + "k";
+ if (damage < 1_000_000_000) return format(damage / 1_000_000.0) + "M";
+ if (damage < 1_000_000_000_000L) return format(damage / 1_000_000_000.0) + "B";
+ return format(damage / 1_000_000_000_000.0) + "T"; //This will probably never be reached
+ }
+
+ private static String format(double number) {
+ return ("%." + SkyblockerConfigManager.get().uiAndVisuals.compactDamage.precision + "f").formatted(number);
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionViewScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionViewScreen.java
index af931eb1..f3db2a25 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionViewScreen.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionViewScreen.java
@@ -5,6 +5,7 @@ import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.render.gui.AbstractCustomHypixelGUI;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.PopupScreen;
+import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.DirectionalLayoutWidget;
import net.minecraft.client.gui.widget.SimplePositioningWidget;
@@ -21,7 +22,9 @@ import net.minecraft.text.TextColor;
import net.minecraft.util.Colors;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
+import org.lwjgl.glfw.GLFW;
+import java.time.Duration;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -56,6 +59,15 @@ public class AuctionViewScreen extends AbstractCustomHypixelGUI<AuctionHouseScre
}
@Override
+ public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
+ if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
+ clickSlot(BACK_BUTTON_SLOT);
+ return true;
+ }
+ return super.keyPressed(keyCode, scanCode, modifiers);
+ }
+
+ @Override
protected void init() {
super.init();
verticalLayout.spacing(2).getMainPositioner().alignHorizontalCenter();
@@ -78,10 +90,13 @@ public class AuctionViewScreen extends AbstractCustomHypixelGUI<AuctionHouseScre
verticalLayout.forEachChild(this::addDrawableChild);
updateLayout();
- addDrawableChild(new ButtonWidget.Builder(Text.literal("<"), button -> this.clickSlot(BACK_BUTTON_SLOT))
+ ButtonWidget backButton = new ButtonWidget.Builder(Text.literal("<"), button -> this.clickSlot(BACK_BUTTON_SLOT))
.position(x + backgroundWidth - 16, y + 4)
.size(12, 12)
- .build());
+ .tooltip(Tooltip.of(Text.literal("or press ESC!")))
+ .build();
+ backButton.setTooltipDelay(Duration.ofSeconds(1));
+ addDrawableChild(backButton);
}
@@ -189,7 +204,7 @@ public class AuctionViewScreen extends AbstractCustomHypixelGUI<AuctionHouseScre
@Override
public void onSlotChange(AuctionHouseScreenHandler handler, int slotId, ItemStack stack) {
- if (stack.isOf(Items.BLACK_STAINED_GLASS_PANE) || slotId == 13) return;
+ if (stack.isOf(Items.BLACK_STAINED_GLASS_PANE) || slotId == 13 || slotId >= handler.getRows() * 9) return;
assert client != null;
if (stack.isOf(Items.RED_TERRACOTTA)) { // Red terracotta shows up when you can cancel it
changeState(BuyState.CANCELLABLE_AUCTION);
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java
index 9d460803..f96e3231 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/EditBidPopup.java
@@ -1,5 +1,7 @@
package de.hysky.skyblocker.skyblock.auction;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.calculators.SignCalculator;
import de.hysky.skyblocker.utils.render.gui.AbstractPopupScreen;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.client.MinecraftClient;
@@ -9,7 +11,6 @@ import net.minecraft.network.packet.c2s.play.UpdateSignC2SPacket;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
-import org.lwjgl.glfw.GLFW;
public class EditBidPopup extends AbstractPopupScreen {
private DirectionalLayoutWidget layout = DirectionalLayoutWidget.vertical();
@@ -55,6 +56,9 @@ public class EditBidPopup extends AbstractPopupScreen {
public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {
super.renderBackground(context, mouseX, mouseY, delta);
drawPopupBackground(context, layout.getX(), layout.getY(), layout.getWidth(), layout.getHeight());
+ if (SkyblockerConfigManager.get().uiAndVisuals.inputCalculator.enabled) {
+ SignCalculator.renderCalculator(context, textFieldWidget.getText(), context.getScaledWindowWidth() / 2, textFieldWidget.getY() - 8);
+ }
}
private boolean isStringGood(String s) {
@@ -69,8 +73,13 @@ public class EditBidPopup extends AbstractPopupScreen {
}
private void done(ButtonWidget widget) {
- if (!isStringGood(textFieldWidget.getText().trim())) return;
- sendPacket(textFieldWidget.getText().trim());
+ if (SkyblockerConfigManager.get().uiAndVisuals.inputCalculator.enabled) {
+ if (!isStringGood(SignCalculator.getNewValue(false))) return;
+ sendPacket(SignCalculator.getNewValue(false));
+ } else {
+ if (!isStringGood(textFieldWidget.getText().trim())) return;
+ sendPacket(textFieldWidget.getText().trim());
+ }
this.close();
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/calculators/CalculatorCommand.java b/src/main/java/de/hysky/skyblocker/skyblock/calculators/CalculatorCommand.java
new file mode 100644
index 00000000..d103bcdd
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/calculators/CalculatorCommand.java
@@ -0,0 +1,56 @@
+package de.hysky.skyblocker.skyblock.calculators;
+
+import com.mojang.brigadier.Command;
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.utils.Calculator;
+import de.hysky.skyblocker.utils.Constants;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.command.CommandRegistryAccess;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
+
+import java.text.NumberFormat;
+
+import static com.mojang.brigadier.arguments.StringArgumentType.getString;
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
+
+public class CalculatorCommand {
+ private static final MinecraftClient CLIENT = MinecraftClient.getInstance();
+ private static final NumberFormat FORMATTER = NumberFormat.getInstance();
+
+ public static void init() {
+ ClientCommandRegistrationCallback.EVENT.register(CalculatorCommand::calculate);
+ }
+
+ private static void calculate(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
+ dispatcher.register(literal(SkyblockerMod.NAMESPACE)
+ .then(literal("calculate")
+ .then(argument("equation", StringArgumentType.greedyString())
+ .executes(context -> doCalculation(getString(context, "equation")))
+ )
+ )
+ );
+ }
+
+ private static int doCalculation(String calculation) {
+ MutableText text = Constants.PREFIX.get();
+ try {
+ text.append(Text.literal(FORMATTER.format(Calculator.calculate(calculation))).formatted(Formatting.GREEN));
+ } catch (UnsupportedOperationException e) {
+ text.append(Text.translatable("skyblocker.config.uiAndVisuals.inputCalculator.invalidEquation").formatted(Formatting.RED));
+ }
+
+ if (CLIENT == null || CLIENT.player == null) {
+ return 0;
+ }
+
+ CLIENT.player.sendMessage(text, false);
+ return Command.SINGLE_SUCCESS;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/calculators/SignCalculator.java b/src/main/java/de/hysky/skyblocker/skyblock/calculators/SignCalculator.java
new file mode 100644
index 00000000..dc51e48c
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/calculators/SignCalculator.java
@@ -0,0 +1,66 @@
+package de.hysky.skyblocker.skyblock.calculators;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.Calculator;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
+
+import java.text.NumberFormat;
+
+public class SignCalculator {
+ private static final MinecraftClient CLIENT = MinecraftClient.getInstance();
+ private static final NumberFormat FORMATTER = NumberFormat.getInstance();
+
+ private static String lastInput;
+ private static double output;
+
+ public static void renderCalculator(DrawContext context, String message, int renderX, int renderY) {
+ if (SkyblockerConfigManager.get().uiAndVisuals.inputCalculator.requiresEquals && !message.startsWith("=")) {
+ output = -1;
+ lastInput = message;
+ return;
+ }
+ if (message.startsWith("=")) {
+ message = message.substring(1);
+ }
+ //only update output if new input
+ if (!message.equals(lastInput)) { //
+ try {
+ output = Calculator.calculate(message);
+ } catch (Exception e) {
+ output = -1;
+ }
+ }
+
+ render(context, message, renderX, renderY);
+
+ lastInput = message;
+ }
+
+ public static String getNewValue(Boolean isPrice) {
+ if (output == -1) {
+ //if mode is not activated or just invalid equation return what the user typed in
+ return lastInput;
+ }
+
+ //price can except decimals and exponents
+ if (isPrice) {
+ return FORMATTER.format(output);
+ }
+ //amounts want an integer number so round
+ return Long.toString(Math.round(output));
+ }
+
+ private static void render(DrawContext context, String input, int renderX, int renderY) {
+ Text text;
+ if (output == -1) {
+ text = Text.translatable("skyblocker.config.uiAndVisuals.inputCalculator.invalidEquation").formatted(Formatting.RED);
+ } else {
+ text = Text.literal(input + " = " + FORMATTER.format(output)).formatted(Formatting.GREEN);
+ }
+
+ context.drawCenteredTextWithShadow(CLIENT.textRenderer, text, renderX, renderY, 0xFFFFFFFF);
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java
index 01673f23..833e85a3 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java
@@ -16,7 +16,7 @@ import org.slf4j.LoggerFactory;
import java.util.*;
-public class ColorTerminal extends ContainerSolver {
+public class ColorTerminal extends ContainerSolver implements TerminalSolver {
private static final Logger LOGGER = LoggerFactory.getLogger(ColorTerminal.class.getName());
private static final Map<String, DyeColor> colorFromName;
private DyeColor targetColor;
@@ -53,6 +53,14 @@ public class ColorTerminal extends ContainerSolver {
return highlights;
}
+ @Override
+ protected boolean onClickSlot(int slot, ItemStack stack, int screenId, String[] groups) {
+ if (stack.hasGlint() || !targetColor.equals(itemColor.get(stack.getItem()))) {
+ return shouldBlockIncorrectClicks();
+ }
+
+ return false;
+ }
static {
colorFromName = new HashMap<>();
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/LightsOnTerminal.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/LightsOnTerminal.java
new file mode 100644
index 00000000..67b51c22
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/LightsOnTerminal.java
@@ -0,0 +1,37 @@
+package de.hysky.skyblocker.skyblock.dungeon.terminal;
+
+import java.util.List;
+
+import de.hysky.skyblocker.utils.render.gui.ColorHighlight;
+import de.hysky.skyblocker.utils.render.gui.ContainerSolver;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
+
+/**
+ * The terminal where you change all the panes that are red to green.
+ *
+ * This doesn't solve the terminal because you don't need a solver for it, but rather to simply allow for click blocking.
+ */
+public class LightsOnTerminal extends ContainerSolver implements TerminalSolver {
+ private static final List<ColorHighlight> EMPTY = List.of();
+
+ public LightsOnTerminal() {
+ super("^Correct all the panes!$");
+ }
+
+ @Override
+ protected boolean isEnabled() {
+ return shouldBlockIncorrectClicks();
+ }
+
+ @Override
+ protected List<ColorHighlight> getColors(String[] groups, Int2ObjectMap<ItemStack> slots) {
+ return EMPTY;
+ }
+
+ @Override
+ protected boolean onClickSlot(int slot, ItemStack stack, int screenId, String[] groups) {
+ return stack.isOf(Items.LIME_STAINED_GLASS_PANE);
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java
index d8d9a63a..e980a136 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java
@@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-public class OrderTerminal extends ContainerSolver {
+public class OrderTerminal extends ContainerSolver implements TerminalSolver {
private final int PANES_NUM = 14;
private int[] orderedSlots;
private int currentNum = Integer.MAX_VALUE;
@@ -55,4 +55,15 @@ public class OrderTerminal extends ContainerSolver {
currentNum = 0;
return true;
}
+
+ @Override
+ protected boolean onClickSlot(int slot, ItemStack stack, int screenId, String[] groups) {
+ if (stack == null || stack.isEmpty()) return false;
+
+ if (!stack.isOf(Items.RED_STAINED_GLASS_PANE) || stack.getCount() != currentNum + 1) {
+ return shouldBlockIncorrectClicks();
+ }
+
+ return false;
+ }
} \ No newline at end of file
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java
index c4cc8e47..51a778a5 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java
@@ -13,7 +13,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
-public class StartsWithTerminal extends ContainerSolver {
+public class StartsWithTerminal extends ContainerSolver implements TerminalSolver {
private final Int2ObjectOpenHashMap<ItemState> trackedItemStates = new Int2ObjectOpenHashMap<>();
private int lastKnownScreenId = Integer.MIN_VALUE;
@@ -50,9 +50,9 @@ public class StartsWithTerminal extends ContainerSolver {
}
@Override
- protected void onClickSlot(int slot, ItemStack stack, int screenId, String[] groups) {
+ protected boolean onClickSlot(int slot, ItemStack stack, int screenId, String[] groups) {
//Some random glass pane was clicked or something
- if (!trackedItemStates.containsKey(slot) || stack == null || stack.isEmpty()) return;
+ if (!trackedItemStates.containsKey(slot) || stack == null || stack.isEmpty()) return false;
ItemState state = trackedItemStates.get(slot);
String prefix = groups[0];
@@ -61,16 +61,17 @@ public class StartsWithTerminal extends ContainerSolver {
//Also, since Hypixel closes & reopens the GUI after every click we check if the last known screen id is the same that way in case the server lags and
//either a player tries to click a second item or if the player puts the clicked item back and tries to click another that we don't mark multiple items
//as clicked when only the first one will count.
-
+
//While Hypixel does use a different syncId each time they open the screen we opt to use our own so as to avoid them potentially changing that
//and in turn breaking this logic
if (stack.getName().getString().startsWith(prefix) && !state.clicked() && lastKnownScreenId != screenId) {
trackedItemStates.put(slot, state.click());
lastKnownScreenId = screenId;
+ } else {
+ return shouldBlockIncorrectClicks();
}
- //In the future we could add an else branch and return a boolean to cancel the click since it would be wrong
- return;
+ return false;
}
//We only setup the state when all items aren't null or empty. This prevents the state from being reset due to unsent items or server lag spikes/bad TPS (fix ur servers Hypixel)
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/TerminalSolver.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/TerminalSolver.java
new file mode 100644
index 00000000..7a7cd6bb
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/terminal/TerminalSolver.java
@@ -0,0 +1,10 @@
+package de.hysky.skyblocker.skyblock.dungeon.terminal;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+
+public interface TerminalSolver {
+
+ default boolean shouldBlockIncorrectClicks() {
+ return SkyblockerConfigManager.get().dungeons.terminals.blockIncorrectClicks;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CommissionLabels.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CommissionLabels.java
new file mode 100644
index 00000000..a14c71f7
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CommissionLabels.java
@@ -0,0 +1,99 @@
+package de.hysky.skyblocker.skyblock.dwarven;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.config.configs.MiningConfig;
+import de.hysky.skyblocker.utils.Utils;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
+import net.minecraft.util.math.BlockPos;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class CommissionLabels {
+
+ private static final Map<String, MiningLocationLabel.DwarvenCategory> DWARVEN_LOCATIONS = Arrays.stream(MiningLocationLabel.DwarvenCategory.values()).collect(Collectors.toMap(MiningLocationLabel.DwarvenCategory::toString, Function.identity()));
+ private static final List<MiningLocationLabel.DwarvenEmissaries> DWARVEN_EMISSARIES = Arrays.stream(MiningLocationLabel.DwarvenEmissaries.values()).toList();
+ private static final Map<String, MiningLocationLabel.GlaciteCategory> GLACITE_LOCATIONS = Arrays.stream(MiningLocationLabel.GlaciteCategory.values()).collect(Collectors.toMap(MiningLocationLabel.GlaciteCategory::toString, Function.identity()));
+
+ protected static List<MiningLocationLabel> activeWaypoints = new ArrayList<>();
+
+ public static void init() {
+ WorldRenderEvents.AFTER_TRANSLUCENT.register(CommissionLabels::render);
+ }
+
+ /**
+ * update the activeWaypoints when there is a change in commissions
+ *
+ * @param newCommissions the new commissions to get the waypoints from
+ * @param completed if there is a commission completed
+ */
+ protected static void update(List<String> newCommissions, boolean completed) {
+ MiningConfig.CommissionWaypointMode currentMode = SkyblockerConfigManager.get().mining.commissionWaypoints.mode;
+ if (currentMode == MiningConfig.CommissionWaypointMode.OFF) {
+ return;
+ }
+ activeWaypoints.clear();
+ String location = Utils.getIslandArea().substring(2);
+ //find commission locations in glacite
+ if (location.equals("Dwarven Base Camp") || location.equals("Glacite Tunnels") || location.equals("Glacite Mineshafts") || location.equals("Glacite Lake")) {
+ if (currentMode != MiningConfig.CommissionWaypointMode.BOTH && currentMode != MiningConfig.CommissionWaypointMode.GLACITE) {
+ return;
+ }
+
+ for (String commission : newCommissions) {
+ for (Map.Entry<String, MiningLocationLabel.GlaciteCategory> glaciteLocation : GLACITE_LOCATIONS.entrySet()) {
+ if (commission.contains(glaciteLocation.getKey())) {
+ MiningLocationLabel.GlaciteCategory category = glaciteLocation.getValue();
+ for (BlockPos gemstoneLocation : category.getLocations()) {
+ activeWaypoints.add(new MiningLocationLabel(category, gemstoneLocation));
+ }
+ }
+ }
+ }
+ //add base waypoint if enabled
+ if (SkyblockerConfigManager.get().mining.commissionWaypoints.showBaseCamp) {
+ activeWaypoints.add(new MiningLocationLabel(MiningLocationLabel.GlaciteCategory.CAMPFIRE, MiningLocationLabel.GlaciteCategory.CAMPFIRE.getLocations()[0]));
+ }
+ return;
+ }
+ //find commission locations in dwarven mines
+ if (currentMode != MiningConfig.CommissionWaypointMode.BOTH && currentMode != MiningConfig.CommissionWaypointMode.DWARVEN) {
+ return;
+ }
+
+ for (String commission : newCommissions) {
+ for (Map.Entry<String, MiningLocationLabel.DwarvenCategory> dwarvenLocation : DWARVEN_LOCATIONS.entrySet()) {
+ if (commission.contains(dwarvenLocation.getKey())) {
+ MiningLocationLabel.DwarvenCategory category = dwarvenLocation.getValue();
+ category.isTitanium = commission.contains("Titanium");
+ activeWaypoints.add(new MiningLocationLabel(category, category.getLocation()));
+ }
+ }
+ }
+ //if there is a commission completed and enabled show emissary
+ if (SkyblockerConfigManager.get().mining.commissionWaypoints.showEmissary && completed) {
+ for (MiningLocationLabel.DwarvenEmissaries emissaries : DWARVEN_EMISSARIES) {
+ activeWaypoints.add(new MiningLocationLabel(emissaries, emissaries.getLocation()));
+ }
+ }
+ }
+
+ /**
+ * render all the active waypoints
+ *
+ * @param context render context
+ */
+ private static void render(WorldRenderContext context) {
+ if (!Utils.isInDwarvenMines() || SkyblockerConfigManager.get().mining.commissionWaypoints.mode == MiningConfig.CommissionWaypointMode.OFF) {
+ return;
+ }
+ for (MiningLocationLabel MiningLocationLabel : activeWaypoints) {
+ MiningLocationLabel.render(context);
+ }
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java
index a74dbc5e..63430489 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java
@@ -21,7 +21,7 @@ import java.util.Map;
public class CrystalsHud {
private static final MinecraftClient CLIENT = MinecraftClient.getInstance();
- protected static final Identifier MAP_TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/crystals_map.png");
+ protected static final Identifier MAP_TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/crystals_map.png");
private static final Identifier MAP_ICON = new Identifier("textures/map/decorations/player.png");
private static final List<String> SMALL_LOCATIONS = List.of("Fairy Grotto", "King Yolkar", "Corleone", "Odawa", "Key Guardian");
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsWaypoint.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsWaypoint.java
index 053f3536..dc40f82c 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsWaypoint.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsWaypoint.java
@@ -42,7 +42,7 @@ public class CrystalsWaypoint extends Waypoint {
@Override
public boolean shouldRender() {
- return super.shouldRender() ;
+ return super.shouldRender();
}
@Override
@@ -84,7 +84,7 @@ public class CrystalsWaypoint extends Waypoint {
private final String name;
private final float[] colorComponents;
- Category(String name,Color color) {
+ Category(String name, Color color) {
this.name = name;
this.color = color;
this.colorComponents = color.getColorComponents(null);
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java
index 242c513a..2cf0ea9d 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java
@@ -168,9 +168,9 @@ public class DwarvenHud {
|| !Utils.isInCrystalHollows() && !Utils.isInDwarvenMines()) {
return;
}
-
+ List<String> oldCommissionNames = commissionList.stream().map(Commission::commission).toList();
+ boolean oldCompleted = commissionList.stream().anyMatch(commission -> commission.progression.equals("DONE"));
commissionList = new ArrayList<>();
-
for (PlayerListEntry playerListEntry : CLIENT.getNetworkHandler().getPlayerList().stream().sorted(PlayerListHudAccessor.getOrdering()).toList()) {
if (playerListEntry.getDisplayName() == null) {
continue;
@@ -197,6 +197,11 @@ public class DwarvenHud {
glacitePowder = glaciteMatcher.group(0).split(": ")[1];
}
}
+ List<String> newCommissionNames = commissionList.stream().map(Commission::commission).toList();
+ boolean newCompleted = commissionList.stream().anyMatch(commission -> commission.progression.equals("DONE"));
+ if (!oldCommissionNames.equals(newCommissionNames) || oldCompleted != newCompleted) {
+ CommissionLabels.update(newCommissionNames, newCompleted);
+ }
}
// steamroller tactics to get visibility from outside classes (HudCommsWidget)
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/MiningLocationLabel.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/MiningLocationLabel.java
new file mode 100644
index 00000000..1f373b55
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/MiningLocationLabel.java
@@ -0,0 +1,157 @@
+package de.hysky.skyblocker.skyblock.dwarven;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.render.RenderHelper;
+import de.hysky.skyblocker.utils.render.Renderable;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3d;
+
+public record MiningLocationLabel(Category category, Vec3d centerPos) implements Renderable {
+ public MiningLocationLabel(Category category, BlockPos pos) {
+ this(category, pos.toCenterPos());
+ }
+
+ private Text getName() {
+ if (SkyblockerConfigManager.get().mining.commissionWaypoints.useColor) {
+ return Text.literal(category.getName()).withColor(category.getColor());
+ }
+ return Text.literal(category.getName());
+ }
+
+ /**
+ * Renders the name and distance to the label scaled so can be seen at a distance
+ * @param context render context
+ */
+ @Override
+ public void render(WorldRenderContext context) {
+ Vec3d posUp = centerPos.add(0, 1, 0);
+ double distance = context.camera().getPos().distanceTo(centerPos);
+ float scale = (float) (SkyblockerConfigManager.get().mining.commissionWaypoints.textScale * (distance / 10));
+ RenderHelper.renderText(context, getName(), posUp, scale, true);
+ RenderHelper.renderText(context, Text.literal(Math.round(distance) + "m").formatted(Formatting.YELLOW), posUp, scale, MinecraftClient.getInstance().textRenderer.fontHeight + 1, true);
+ }
+
+ public interface Category {
+ String getName();
+
+ int getColor(); //all the color codes are the color of the block the waypoint is for
+ }
+
+ enum DwarvenCategory implements Category {
+ LAVA_SPRINGS("Lava Springs", new BlockPos(60, 197, -15)),
+ CLIFFSIDE_VEINS("Cliffside Veins", new BlockPos(40, 128, 40)),
+ RAMPARTS_QUARRY("Rampart's Quarry", new BlockPos(-100, 150, -20)),
+ UPPER_MINES("Upper Mines", new BlockPos(-130, 174, -50)),
+ ROYAL_MINES("Royal Mines", new BlockPos(130, 154, 30)),
+ GLACITE_WALKER("Glacite Walker", new BlockPos(0, 128, 150));
+
+
+ boolean isTitanium;
+ private final String name;
+ private final BlockPos location;
+
+ DwarvenCategory(String name, BlockPos location) {
+ this.name = name;
+ this.location = location;
+ }
+
+ public BlockPos getLocation() {
+ return location;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int getColor() {
+ if (isTitanium) {
+ return 0xd8d6d8;
+ }
+ return 0x45bde0;
+ }
+ }
+
+ enum DwarvenEmissaries implements Category {
+ LAVA_SPRINGS(new BlockPos(58, 198, -8)),
+ CLIFFSIDE_VEINS(new BlockPos(42, 134, 22)),
+ RAMPARTS_QUARRY(new BlockPos(-72, 153, -10)),
+ UPPER_MINES(new BlockPos(-132, 174, -50)),
+ ROYAL_MINES(new BlockPos(171, 150, 31)),
+ DWARVEN_VILLAGE(new BlockPos(-37, 200, -92)),
+ DWARVEN_MINES(new BlockPos(89, 198, -92));
+
+ private final BlockPos location;
+
+ DwarvenEmissaries(BlockPos location) {
+
+ this.location = location;
+ }
+
+ public BlockPos getLocation() {
+ return location;
+ }
+
+ @Override
+ public String toString() {
+ return "Emissary";
+ }
+
+ @Override
+ public String getName() {
+ return "Emissary";
+ }
+
+ @Override
+ public int getColor() {
+ return 0xffffff;
+ }
+ }
+
+ enum GlaciteCategory implements Category {
+ AQUAMARINE("Aquamarine", 0x334cb1, new BlockPos[]{new BlockPos(-1, 139, 437), new BlockPos(90, 151, 229), new BlockPos(56, 151, 400), new BlockPos(51, 117, 303)}),
+ ONYX("Onyx", 0x191919, new BlockPos[]{new BlockPos(79, 119, 411), new BlockPos(-14, 132, 386), new BlockPos(18, 136, 370), new BlockPos(16, 138, 411), new BlockPos(-68, 130, 408)}),
+ PERIDOT("Peridot", 0x667f33, new BlockPos[]{new BlockPos(-61, 147, 302), new BlockPos(91, 122, 397), new BlockPos(-73, 122, 458), new BlockPos(-77, 120, 282)}),
+ CITRINE("Citrine", 0x664c33, new BlockPos[]{new BlockPos(-104, 144, 244), new BlockPos(39, 119, 386), new BlockPos(-57, 144, 421), new BlockPos(-47, 126, 418)}),
+ CAMPFIRE("Base Camp", 0x983333, new BlockPos[]{new BlockPos(-7, 126, 229)});
+
+ private final String name;
+ private final int color;
+ private final BlockPos[] location;
+
+ GlaciteCategory(String name, int color, BlockPos[] location) {
+ this.name = name;
+ this.color = color;
+ this.location = location;
+ }
+
+ public BlockPos[] getLocations() {
+ return location;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int getColor() {
+ return color;
+ }
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/foraging/ModernForagingIsland.java b/src/main/java/de/hysky/skyblocker/skyblock/foraging/ModernForagingIsland.java
new file mode 100644
index 00000000..fd256681
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/foraging/ModernForagingIsland.java
@@ -0,0 +1,8 @@
+package de.hysky.skyblocker.skyblock.foraging;
+
+public class ModernForagingIsland {
+
+ public static void init() {
+
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java
index 4440cd84..76e7f02c 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java
@@ -109,7 +109,7 @@ public class CustomArmorAnimatedDyes {
}
//Credit to https://codepen.io/OliverBalfour/post/programmatically-making-gradients
- private static int interpolate(int firstColor, int secondColor, double percentage) {
+ public static int interpolate(int firstColor, int secondColor, double percentage) {
int r1 = MathHelper.square((firstColor >> 16) & 0xFF);
int g1 = MathHelper.square((firstColor >> 8) & 0xFF);
int b1 = MathHelper.square(firstColor & 0xFF);
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
index d2fda215..c6caaf41 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
@@ -40,6 +40,8 @@ public class ItemTooltip {
public static void getTooltip(ItemStack stack, Item.TooltipContext tooltipContext, TooltipType tooltipType, List<Text> lines) {
if (!Utils.isOnSkyblock() || client.player == null) return;
+ smoothenLines(lines);
+
String name = getInternalNameFromNBT(stack, false);
String internalID = getInternalNameFromNBT(stack, true);
String neuName = name;
@@ -392,6 +394,15 @@ public class ItemTooltip {
return message;
}
+ private static void smoothenLines(List<Text> lines) {
+ for (int i = 0; i < lines.size(); i++) {
+ Text line = lines.get(i);
+ if (line.getString().equals("-----------------")) {
+ lines.set(i, Text.literal(" ").formatted(Formatting.DARK_GRAY, Formatting.STRIKETHROUGH, Formatting.BOLD));
+ }
+ }
+ }
+
// If these options is true beforehand, the client will get first data of these options while loading.
// After then, it will only fetch the data if it is on Skyblock.
public static int minute = 0;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java
index 5529e466..5fa517cc 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java
@@ -1,17 +1,14 @@
package de.hysky.skyblocker.skyblock.quicknav;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.config.configs.QuickNavigationConfig;
-import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.datafixer.ItemStackComponentizationFixer;
-import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
-import net.fabricmc.fabric.api.client.screen.v1.Screens;
import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.network.ClientPlayerEntity;
-import net.minecraft.nbt.StringNbtReader;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.slf4j.Logger;
@@ -19,22 +16,11 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
import java.util.regex.PatternSyntaxException;
public class QuickNav {
private static final Logger LOGGER = LoggerFactory.getLogger(QuickNav.class);
- public static void init() {
- ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
- if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().quickNav.enableQuickNav && screen instanceof HandledScreen<?> && client.player != null && !client.player.isCreative()) {
- String screenTitle = screen.getTitle().getString().trim();
- List<QuickNavButton> buttons = QuickNav.init(screenTitle);
- for (QuickNavButton button : buttons) Screens.getButtons(screen).add(button);
- }
- });
- }
-
public static List<QuickNavButton> init(String screenTitle) {
List<QuickNavButton> buttons = new ArrayList<>();
QuickNavigationConfig data = SkyblockerConfigManager.get().quickNav;
@@ -51,6 +37,8 @@ public class QuickNav {
if (data.button10.render) buttons.add(parseButton(data.button10, screenTitle, 9));
if (data.button11.render) buttons.add(parseButton(data.button11, screenTitle, 10));
if (data.button12.render) buttons.add(parseButton(data.button12, screenTitle, 11));
+ if (data.button13.render) buttons.add(parseButton(data.button13, screenTitle, 12));
+ if (data.button14.render) buttons.add(parseButton(data.button14, screenTitle, 13));
} catch (CommandSyntaxException e) {
LOGGER.error("[Skyblocker] Failed to initialize Quick Nav Button", e);
}
@@ -58,23 +46,19 @@ public class QuickNav {
}
private static QuickNavButton parseButton(QuickNavigationConfig.QuickNavItem buttonInfo, String screenTitle, int id) throws CommandSyntaxException {
- QuickNavigationConfig.ItemData itemData = buttonInfo.item;
- String nbtString = "{id:\"minecraft:" + itemData.id.toLowerCase(Locale.ROOT) + "\",Count:1";
- if (itemData.nbt.length() > 2) nbtString += "," + itemData.nbt;
- nbtString += "}";
+ QuickNavigationConfig.ItemData itemData = buttonInfo.itemData;
+ ItemStack stack = itemData != null && itemData.item != null && itemData.components != null ? ItemStackComponentizationFixer.fromComponentsString(itemData.item.toString(), Math.clamp(itemData.count, 1, 99), itemData.components) : new ItemStack(Items.BARRIER);
+
boolean uiTitleMatches = false;
try {
uiTitleMatches = screenTitle.matches(buttonInfo.uiTitle);
} catch (PatternSyntaxException e) {
- LOGGER.error("[Skyblocker] Failed to parse Quick Nav Button", e);
+ LOGGER.error("[Skyblocker] Failed to parse Quick Nav Button with regex: {}", buttonInfo.uiTitle, e);
ClientPlayerEntity player = MinecraftClient.getInstance().player;
if (player != null) {
- player.sendMessage(Text.of(Formatting.RED + "[Skyblocker] Invalid regex in quicknav button " + (id + 1) + "!"), false);
+ player.sendMessage(Constants.PREFIX.get().append(Text.literal("Invalid regex in Quick Nav Button " + (id + 1) + "!").formatted(Formatting.RED)), false);
}
}
- return new QuickNavButton(id,
- uiTitleMatches,
- buttonInfo.clickEvent,
- ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse(nbtString)));
+ return new QuickNavButton(id, uiTitleMatches, buttonInfo.clickEvent, stack);
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java
index 7db78590..f9ca0940 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java
@@ -1,7 +1,6 @@
package de.hysky.skyblocker.skyblock.quicknav;
import com.mojang.blaze3d.systems.RenderSystem;
-
import de.hysky.skyblocker.mixins.accessors.HandledScreenAccessor;
import de.hysky.skyblocker.utils.scheduler.MessageScheduler;
import net.fabricmc.api.EnvType;
@@ -16,7 +15,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
-@Environment(value=EnvType.CLIENT)
+@Environment(value = EnvType.CLIENT)
public class QuickNavButton extends ClickableWidget {
private final int index;
private boolean toggled;
@@ -25,18 +24,24 @@ public class QuickNavButton extends ClickableWidget {
/**
* Checks if the current tab is a top tab based on its index.
- * @return true if the index is less than 6, false otherwise.
+ *
+ * @return true if the index is less than 7, false otherwise.
*/
private boolean isTopTab() {
- return index < 6;
+ return index < 7;
+ }
+
+ public boolean toggled() {
+ return toggled;
}
/**
* Constructs a new QuickNavButton with the given parameters.
- * @param index the index of the button.
+ *
+ * @param index the index of the button.
* @param toggled the toggled state of the button.
* @param command the command to execute when the button is clicked.
- * @param icon the icon to display on the button.
+ * @param icon the icon to display on the button.
*/
public QuickNavButton(int index, boolean toggled, String command, ItemStack icon) {
super(0, 0, 26, 32, Text.empty());
@@ -49,18 +54,18 @@ public class QuickNavButton extends ClickableWidget {
private void updateCoordinates() {
Screen screen = MinecraftClient.getInstance().currentScreen;
if (screen instanceof HandledScreen<?> handledScreen) {
- int x = ((HandledScreenAccessor)handledScreen).getX();
- int y = ((HandledScreenAccessor)handledScreen).getY();
- int h = ((HandledScreenAccessor)handledScreen).getBackgroundHeight();
- if (h > 166) --h; // why is this even a thing
- this.setX(x + this.index % 6 * 26 + 4);
- this.setY(this.index < 6 ? y - 26 : y + h - 4);
+ int x = ((HandledScreenAccessor) handledScreen).getX();
+ int y = ((HandledScreenAccessor) handledScreen).getY();
+ int h = ((HandledScreenAccessor) handledScreen).getBackgroundHeight();
+ this.setX(x + this.index % 7 * 25);
+ this.setY(this.index < 7 ? y - 28 : y + h - 4);
}
}
/**
* Handles click events. If the button is not currently toggled,
* it sets the toggled state to true and sends a message with the command after cooldown.
+ *
* @param mouseX the x-coordinate of the mouse click
* @param mouseY the y-coordinate of the mouse click
*/
@@ -78,9 +83,10 @@ public class QuickNavButton extends ClickableWidget {
* The method first updates the coordinates of the button,
* then calculates appropriate values for rendering based on its current state,
* and finally draws both the background and icon of the button on screen.
+ *
* @param context the context in which to render the button
- * @param mouseX the x-coordinate of the mouse cursor
- * @param mouseY the y-coordinate of the mouse cursor
+ * @param mouseX the x-coordinate of the mouse cursor
+ * @param mouseY the y-coordinate of the mouse cursor
*/
@Override
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
@@ -88,31 +94,16 @@ public class QuickNavButton extends ClickableWidget {
RenderSystem.disableDepthTest();
// Construct the texture identifier based on the index and toggled state
- String tabType = isTopTab() ? "top" : "bottom";
- Identifier BUTTON_TEXTURES = new Identifier("container/creative_inventory/tab_" + tabType +
- (toggled ? "_selected_" : "_unselected_") + 2);
+ Identifier tabTexture = new Identifier("container/creative_inventory/tab_" + (isTopTab() ? "top" : "bottom") + "_" + (toggled ? "selected" : "unselected") + "_" + (index % 7 + 1));
// Render the button texture
- int y = this.getY();
- if (this.toggled) {
- if (this.index < 6) y -= 2;
- } else {
- y += (this.index >= 6) ? 4 : -2;
- }
- int height = this.height - ((this.toggled ) ? 0 : 4);
-
- context.drawGuiTexture(BUTTON_TEXTURES, this.getX(), y, this.width, height);
-
+ context.drawGuiTexture(tabTexture, this.getX(), this.getY(), this.width, this.height);
// Render the button icon
- int yOffset = !this.toggled && this.index < 6 ? 1 : 0;
- context.drawItem(this.icon, this.getX() + 5, this.getY() + 6 + yOffset);
-
+ int yOffset = this.index < 7 ? 1 : -1;
+ context.drawItem(this.icon, this.getX() + 5, this.getY() + 8 + yOffset);
RenderSystem.enableDepthTest();
}
- @Override
- protected void appendClickableNarrations(NarrationMessageBuilder builder) {
- // TODO Auto-generated method stub
-
- }
+ @Override
+ protected void appendClickableNarrations(NarrationMessageBuilder builder) {}
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/Calculator.java b/src/main/java/de/hysky/skyblocker/utils/Calculator.java
new file mode 100644
index 00000000..7b0baaf6
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/Calculator.java
@@ -0,0 +1,208 @@
+package de.hysky.skyblocker.utils;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Calculator {
+ public enum TokenType {
+ NUMBER, OPERATOR, L_PARENTHESIS, R_PARENTHESIS
+ }
+
+ public static class Token {
+ public TokenType type;
+ String value;
+ int tokenLength;
+ }
+
+ private static final Pattern NUMBER_PATTERN = Pattern.compile("(\\d+\\.?\\d*)([sekmbt]?)");
+ private static final Map<String, Long> MAGNITUDE_VALUES = Map.of(
+ "s", 64L,
+ "e", 160L,
+ "k", 1_000L,
+ "m", 1_000_000L,
+ "b", 1_000_000_000L,
+ "t", 1_000_000_000_000L
+ );
+
+ private static List<Token> lex(String input) {
+ List<Token> tokens = new ArrayList<>();
+ input = input.replace(" ", "").toLowerCase().replace("x", "*");
+ int i = 0;
+ while (i < input.length()) {
+ Token token = new Token();
+ switch (input.charAt(i)) {
+ case '+', '-', '*', '/' -> {
+ token.type = TokenType.OPERATOR;
+ token.value = String.valueOf(input.charAt(i));
+ token.tokenLength = 1;
+ }
+
+ case '(' -> {
+ token.type = TokenType.L_PARENTHESIS;
+ token.value = String.valueOf(input.charAt(i));
+ token.tokenLength = 1;
+ //add implicit multiplication when there is a number before brackets
+ if (!tokens.isEmpty()) {
+ TokenType lastType = tokens.getLast().type;
+ if (lastType == TokenType.R_PARENTHESIS || lastType == TokenType.NUMBER) {
+ Token mutliplyToken = new Token();
+ mutliplyToken.type = TokenType.OPERATOR;
+ mutliplyToken.value = "*";
+ tokens.add(mutliplyToken);
+ }
+ }
+ }
+
+ case ')' -> {
+ token.type = TokenType.R_PARENTHESIS;
+ token.value = String.valueOf(input.charAt(i));
+ token.tokenLength = 1;
+ }
+
+ default -> {
+ token.type = TokenType.NUMBER;
+ Matcher numberMatcher = NUMBER_PATTERN.matcher(input.substring(i));
+ if (!numberMatcher.find()) {//invalid value to lex
+ throw new UnsupportedOperationException("invalid character");
+ }
+ int end = numberMatcher.end();
+ token.value = input.substring(i, i + end);
+ token.tokenLength = end;
+ }
+ }
+ tokens.add(token);
+
+ i += token.tokenLength;
+ }
+
+ return tokens;
+ }
+
+ /**
+ * This is an implementation of the shunting yard algorithm to convert the equation to reverse polish notation
+ *
+ * @param tokens equation in infix notation order
+ * @return equation in RPN order
+ */
+ private static List<Token> shunt(List<Token> tokens) {
+ Deque<Token> operatorStack = new ArrayDeque<>();
+ List<Token> outputQueue = new ArrayList<>();
+
+ for (Token shuntingToken : tokens) {
+ switch (shuntingToken.type) {
+ case NUMBER -> outputQueue.add(shuntingToken);
+ case OPERATOR -> {
+ int precedence = getPrecedence(shuntingToken.value);
+ while (!operatorStack.isEmpty()) {
+ Token leftToken = operatorStack.peek();
+ if (leftToken.type == TokenType.L_PARENTHESIS) {
+ break;
+ }
+ assert (leftToken.type == TokenType.OPERATOR);
+ int leftPrecedence = getPrecedence(leftToken.value);
+ if (leftPrecedence >= precedence) {
+ outputQueue.add(operatorStack.pop());
+ continue;
+ }
+ break;
+ }
+ operatorStack.push(shuntingToken);
+ }
+ case L_PARENTHESIS -> operatorStack.push(shuntingToken);
+ case R_PARENTHESIS -> {
+ while (true) {
+ if (operatorStack.isEmpty()) {
+ throw new UnsupportedOperationException("Unbalanced left parenthesis");
+ }
+ Token leftToken = operatorStack.pop();
+ if (leftToken.type == TokenType.L_PARENTHESIS) {
+ break;
+ }
+ outputQueue.add(leftToken);
+ }
+ }
+ }
+ }
+ //empty the operator stack
+ while (!operatorStack.isEmpty()) {
+ Token leftToken = operatorStack.pop();
+ if (leftToken.type == TokenType.L_PARENTHESIS) {
+ //technically unbalanced left parenthesis error but just assume they are close after the equation and ignore them from here
+ continue;
+ }
+ outputQueue.add(leftToken);
+ }
+
+ return outputQueue.stream().toList();
+ }
+
+ private static int getPrecedence(String operator) {
+ switch (operator) {
+ case "+", "-" -> {
+ return 0;
+ }
+ case "*", "/" -> {
+ return 1;
+ }
+ default -> throw new UnsupportedOperationException("Invalid operator");
+ }
+ }
+
+ /**
+ * @param tokens list of Tokens in reverse polish notation
+ * @return answer to equation
+ */
+ private static double evaluate(List<Token> tokens) {
+ Deque<Double> values = new ArrayDeque<>();
+ for (Token token : tokens) {
+ switch (token.type) {
+ case NUMBER -> values.push(calculateValue(token.value));
+ case OPERATOR -> {
+ double right = values.pop();
+ double left = values.pop();
+ switch (token.value) {
+ case "+" -> values.push(left + right);
+ case "-" -> values.push(left - right);
+ case "/" -> {
+ if (right == 0) {
+ throw new UnsupportedOperationException("Can not divide by 0");
+ }
+ values.push(left / right);
+ }
+ case "*" -> values.push(left * right);
+ }
+ }
+ case L_PARENTHESIS, R_PARENTHESIS -> throw new UnsupportedOperationException("Equation is not in RPN");
+ }
+ }
+ if (values.isEmpty()) {
+ throw new UnsupportedOperationException("Equation is empty");
+ }
+ return values.pop();
+ }
+
+ private static double calculateValue(String value) {
+ Matcher numberMatcher = NUMBER_PATTERN.matcher(value.toLowerCase());
+ if (!numberMatcher.matches()) {
+ throw new UnsupportedOperationException("Invalid number");
+ }
+ double number = Double.parseDouble(numberMatcher.group(1));
+ String magnitude = numberMatcher.group(2);
+
+ if (!magnitude.isEmpty()) {
+ if (!MAGNITUDE_VALUES.containsKey(magnitude)) {//its invalid if its another letter
+ throw new UnsupportedOperationException("Invalid magnitude");
+ }
+ number *= MAGNITUDE_VALUES.get(magnitude);
+ }
+
+ return number;
+ }
+
+ public static double calculate(String equation) {
+ //custom bit for replacing purse with its value
+ equation = equation.toLowerCase().replaceAll("p(urse)?", String.valueOf(Utils.getPurse()));
+ return evaluate(shunt(lex(equation)));
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
index 086686a7..1aa77080 100644
--- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
@@ -1,6 +1,5 @@
package de.hysky.skyblocker.utils;
-import com.google.gson.Gson;
import com.google.gson.JsonParser;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
@@ -9,6 +8,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.codecs.RecordCodecBuilder;
+import de.hysky.skyblocker.SkyblockerMod;
import it.unimi.dsi.fastutil.ints.IntIntPair;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.component.ComponentChanges;
@@ -49,7 +49,6 @@ public class ItemUtils {
private static final DateTimeFormatter OLD_OBTAINED_DATE_FORMAT = DateTimeFormatter.ofPattern("M/d/yy h:m a").withZone(ZoneId.of("UTC")).localizedBy(Locale.ENGLISH);
public static final Pattern NOT_DURABILITY = Pattern.compile("[^0-9 /]");
public static final Predicate<String> FUEL_PREDICATE = line -> line.contains("Fuel: ");
- private static final Gson GSON = new Gson(); //GSON Instance with no config
private static final Codec<RegistryEntry<Item>> EMPTY_ALLOWING_ITEM_CODEC = Registries.ITEM.getEntryCodec();
public static final Codec<ItemStack> EMPTY_ALLOWING_ITEMSTACK_CODEC = Codec.lazyInitialized(() -> RecordCodecBuilder.create(instance -> instance.group(
EMPTY_ALLOWING_ITEM_CODEC.fieldOf("id").forGetter(ItemStack::getRegistryEntry),
@@ -59,7 +58,7 @@ public class ItemUtils {
public static LiteralArgumentBuilder<FabricClientCommandSource> dumpHeldItemCommand() {
return literal("dumpHeldItem").executes(context -> {
- context.getSource().sendFeedback(Text.literal("[Skyblocker Debug] Held Item: " + GSON.toJson(ItemStack.CODEC.encodeStart(JsonOps.INSTANCE, context.getSource().getPlayer().getMainHandStack()).getOrThrow())));
+ context.getSource().sendFeedback(Text.literal("[Skyblocker Debug] Held Item: " + SkyblockerMod.GSON_COMPACT.toJson(ItemStack.CODEC.encodeStart(JsonOps.INSTANCE, context.getSource().getPlayer().getMainHandStack()).getOrThrow())));
return Command.SINGLE_SUCCESS;
});
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/Location.java b/src/main/java/de/hysky/skyblocker/utils/Location.java
index d5214afd..1f6c93a0 100644
--- a/src/main/java/de/hysky/skyblocker/utils/Location.java
+++ b/src/main/java/de/hysky/skyblocker/utils/Location.java
@@ -87,6 +87,10 @@ public enum Location {
*/
GLACITE_MINESHAFT("mineshaft"),
/**
+ * Goodbye 1.8 hello 1.21 (and foraging 50 for all)!
+ */
+ MODERN_FORAGING_ISLAND("placeholder"),
+ /**
* Unknown Skyblock location
*/
UNKNOWN("unknown");
diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java
index 70dbdac6..62a3b897 100644
--- a/src/main/java/de/hysky/skyblocker/utils/Utils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java
@@ -74,6 +74,8 @@ public class Utils {
private static long clientWorldJoinTime = 0;
private static boolean sentLocRaw = false;
private static boolean canSendLocRaw = false;
+ //This is required to prevent the location change event from being fired twice.
+ private static boolean locationChanged = true;
private static String mayor = "";
@@ -118,6 +120,10 @@ public class Utils {
return location == Location.KUUDRAS_HOLLOW;
}
+ public static boolean isInModernForagingIsland() {
+ return location == Location.MODERN_FORAGING_ISLAND;
+ }
+
public static boolean isInjected() {
return isInjected;
}
@@ -379,6 +385,7 @@ public class Utils {
MessageScheduler.INSTANCE.sendMessageAfterCooldown("/locraw");
sentLocRaw = true;
canSendLocRaw = false;
+ locationChanged = true;
}
} else {
resetLocRawInfo();
@@ -409,6 +416,11 @@ public class Utils {
if (locRaw.has("map")) {
map = locRaw.get("map").getAsString();
}
+
+ if (locationChanged) {
+ SkyblockEvents.LOCATION_CHANGE.invoker().onSkyblockLocationChange(location);
+ locationChanged = false;
+ }
}
/**
diff --git a/src/main/java/de/hysky/skyblocker/utils/datafixer/JsonHelper.java b/src/main/java/de/hysky/skyblocker/utils/datafixer/JsonHelper.java
new file mode 100644
index 00000000..f7646d31
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/datafixer/JsonHelper.java
@@ -0,0 +1,107 @@
+package de.hysky.skyblocker.utils.datafixer;
+
+import java.util.Optional;
+import java.util.OptionalInt;
+
+import com.google.gson.JsonObject;
+
+import net.minecraft.util.annotation.MethodsReturnNonnullByDefault;
+
+/**
+ * Helper methods to assist in retrieving values nested in JSON objects.
+ *
+ * All methods are fully null safe, whether it be from passing a {@code null} root object or from encountering a nonexistent or null object/value.
+ *
+ * @author AzureAaron
+ * @see <a href="https://github.com/AzureAaron/aaron-mod/blob/1.20/src/main/java/net/azureaaron/mod/utils/JsonHelper.java">Aaron's Mod's JSON Helper</a>
+ */
+@MethodsReturnNonnullByDefault
+public class JsonHelper {
+
+ public static OptionalInt getInt(JsonObject root, String path) {
+ //If root is null
+ if (root == null) return OptionalInt.empty();
+
+ //Fast path for if we just want the field itself
+ if (!path.contains(".")) {
+ return root.has(path) && !root.get(path).isJsonNull() ? OptionalInt.of(root.get(path).getAsInt()) : OptionalInt.empty();
+ }
+
+ String[] split = path.split("\\.");
+ String propertyName = split[split.length - 1];
+ String[] objects2Traverse = new String[split.length - 1];
+
+ //Get the traversal path
+ System.arraycopy(split, 0, objects2Traverse, 0, split.length - 1);
+
+ JsonObject currentLevel = root;
+
+ for (String objectName : objects2Traverse) {
+ if (currentLevel.has(objectName) && !currentLevel.get(objectName).isJsonNull()) {
+ currentLevel = currentLevel.getAsJsonObject(objectName);
+ } else {
+ return OptionalInt.empty();
+ }
+ }
+
+ return currentLevel.has(propertyName) && !currentLevel.get(propertyName).isJsonNull() ? OptionalInt.of(currentLevel.get(propertyName).getAsInt()) : OptionalInt.empty();
+ }
+
+ public static Optional<Boolean> getBoolean(JsonObject root, String path) {
+ //If root is null
+ if (root == null) return Optional.empty();
+
+ //Fast path for if we just want the field itself
+ if (!path.contains(".")) {
+ return root.has(path) && !root.get(path).isJsonNull() ? Optional.of(root.get(path).getAsBoolean()) : Optional.empty();
+ }
+
+ String[] split = path.split("\\.");
+ String propertyName = split[split.length - 1];
+ String[] objects2Traverse = new String[split.length - 1];
+
+ //Get the traversal path
+ System.arraycopy(split, 0, objects2Traverse, 0, split.length - 1);
+
+ JsonObject currentLevel = root;
+
+ for (String objectName : objects2Traverse) {
+ if (currentLevel.has(objectName) && !currentLevel.get(objectName).isJsonNull()) {
+ currentLevel = currentLevel.getAsJsonObject(objectName);
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ return currentLevel.has(propertyName) && !currentLevel.get(propertyName).isJsonNull() ? Optional.of(currentLevel.get(propertyName).getAsBoolean()) : Optional.empty();
+ }
+
+ public static Optional<String> getString(JsonObject root, String path) {
+ //If root is null
+ if (root == null) return Optional.empty();
+
+ //Fast path for if we just want the field itself
+ if (!path.contains(".")) {
+ return root.has(path) && !root.get(path).isJsonNull() ? Optional.of(root.get(path).getAsString()) : Optional.empty();
+ }
+
+ String[] split = path.split("\\.");
+ String propertyName = split[split.length - 1];
+ String[] objects2Traverse = new String[split.length - 1];
+
+ //Get the traversal path
+ System.arraycopy(split, 0, objects2Traverse, 0, split.length - 1);
+
+ JsonObject currentLevel = root;
+
+ for (String objectName : objects2Traverse) {
+ if (currentLevel.has(objectName) && !currentLevel.get(objectName).isJsonNull()) {
+ currentLevel = currentLevel.getAsJsonObject(objectName);
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ return currentLevel.has(propertyName) && !currentLevel.get(propertyName).isJsonNull() ? Optional.of(currentLevel.get(propertyName).getAsString()) : Optional.empty();
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolver.java b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolver.java
index e2e057b3..0417dc3c 100644
--- a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolver.java
+++ b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolver.java
@@ -20,7 +20,7 @@ public abstract class ContainerSolver {
protected abstract boolean isEnabled();
- public Pattern getName() {
+ public final Pattern getName() {
return containerName;
}
@@ -34,12 +34,13 @@ public abstract class ContainerSolver {
SkyblockerMod.getInstance().containerSolverManager.markDirty();
}
- protected void onClickSlot(int slot, ItemStack stack, int screenId, String[] groups) {
+ protected boolean onClickSlot(int slot, ItemStack stack, int screenId, String[] groups) {
+ return false;
}
protected abstract List<ColorHighlight> getColors(String[] groups, Int2ObjectMap<ItemStack> slots);
- protected void trimEdges(Int2ObjectMap<ItemStack> slots, int rows) {
+ protected final void trimEdges(Int2ObjectMap<ItemStack> slots, int rows) {
for (int i = 0; i < rows; i++) {
slots.remove(9 * i);
slots.remove(9 * i + 8);
diff --git a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java
index b37c57a4..08fb6a86 100644
--- a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java
+++ b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java
@@ -8,6 +8,7 @@ import de.hysky.skyblocker.skyblock.accessories.newyearcakes.NewYearCakesHelper;
import de.hysky.skyblocker.skyblock.dungeon.CroesusHelper;
import de.hysky.skyblocker.skyblock.dungeon.CroesusProfit;
import de.hysky.skyblocker.skyblock.dungeon.terminal.ColorTerminal;
+import de.hysky.skyblocker.skyblock.dungeon.terminal.LightsOnTerminal;
import de.hysky.skyblocker.skyblock.dungeon.terminal.OrderTerminal;
import de.hysky.skyblocker.skyblock.dungeon.terminal.StartsWithTerminal;
import de.hysky.skyblocker.skyblock.experiment.ChronomatronSolver;
@@ -47,6 +48,7 @@ public class ContainerSolverManager {
new ColorTerminal(),
new OrderTerminal(),
new StartsWithTerminal(),
+ new LightsOnTerminal(),
new CroesusHelper(),
new CroesusProfit(),
new ChronomatronSolver(),
@@ -114,10 +116,15 @@ public class ContainerSolverManager {
highlights = null;
}
- public void onSlotClick(int slot, ItemStack stack) {
+ /**
+ * @return Whether the click should be disallowed.
+ */
+ public boolean onSlotClick(int slot, ItemStack stack) {
if (currentSolver != null) {
- currentSolver.onClickSlot(slot, stack, screenId, groups);
+ return currentSolver.onClickSlot(slot, stack, screenId, groups);
}
+
+ return false;
}
public void onDraw(DrawContext context, List<Slot> slots) {