aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/de/hysky/skyblocker/SkyblockerMod.java10
-rw-r--r--src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java5
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java15
-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.java144
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java22
-rw-r--r--src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java6
-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.java85
-rw-r--r--src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java11
-rw-r--r--src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixer.java90
-rw-r--r--src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix1.java227
-rw-r--r--src/main/java/de/hysky/skyblocker/config/datafixer/ConfigSchema.java29
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java24
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/SignEditScreenMixin.java44
-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/item/tooltip/ItemTooltip.java11
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java11
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Calculator.java208
-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
-rw-r--r--src/main/resources/assets/skyblocker/lang/en_us.json34
-rw-r--r--src/main/resources/skyblocker.mixins.json1
39 files changed, 1510 insertions, 194 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
index 3336cefb..77b1ec2a 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;
@@ -101,6 +100,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();
@@ -123,6 +123,7 @@ public class SkyblockerMod implements ClientModInitializer {
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..b7a711ab 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();
diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java
index 4b8e56df..688b85aa 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 = 2;
+ 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)
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/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..64c67417 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/QuickNavigationCategory.java
@@ -48,14 +48,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button1.item.components,
+ () -> config.quickNav.button1.item.components,
+ newValue -> config.quickNav.button1.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -97,14 +97,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button2.item.components,
+ () -> config.quickNav.button2.item.components,
+ newValue -> config.quickNav.button2.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -146,14 +146,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button3.item.components,
+ () -> config.quickNav.button3.item.components,
+ newValue -> config.quickNav.button3.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -195,14 +195,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button4.item.components,
+ () -> config.quickNav.button4.item.components,
+ newValue -> config.quickNav.button4.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -244,14 +244,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button5.item.components,
+ () -> config.quickNav.button5.item.components,
+ newValue -> config.quickNav.button5.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -293,14 +293,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button6.item.components,
+ () -> config.quickNav.button6.item.components,
+ newValue -> config.quickNav.button6.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -342,14 +342,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button7.item.components,
+ () -> config.quickNav.button7.item.components,
+ newValue -> config.quickNav.button7.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -391,14 +391,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button8.item.components,
+ () -> config.quickNav.button8.item.components,
+ newValue -> config.quickNav.button8.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -440,14 +440,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button9.item.components,
+ () -> config.quickNav.button9.item.components,
+ newValue -> config.quickNav.button9.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -489,14 +489,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button10.item.components,
+ () -> config.quickNav.button10.item.components,
+ newValue -> config.quickNav.button10.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -538,14 +538,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button11.item.components,
+ () -> config.quickNav.button11.item.components,
+ newValue -> config.quickNav.button11.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
@@ -587,14 +587,14 @@ public class QuickNavigationCategory {
.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))
+ .controller(opt -> IntegerFieldControllerBuilder.create(opt).range(1, 99))
.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)
+ .name(Text.translatable("skyblocker.config.quickNav.button.item.components"))
+ .description(OptionDescription.of(Text.translatable("skyblocker.config.quickNav.button.item.components.@Tooltip")))
+ .binding(defaults.quickNav.button12.item.components,
+ () -> config.quickNav.button12.item.components,
+ newValue -> config.quickNav.button12.item.components = newValue)
.controller(StringControllerBuilder::create)
.build())
.option(Option.<String>createBuilder()
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 94ecbc9e..369a9a90 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java
@@ -336,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"))
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/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..ba863e33 100644
--- a/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/configs/QuickNavigationConfig.java
@@ -25,12 +25,12 @@ public class QuickNavigationConfig {
*/
@SerialEntry
public QuickNavItem button4 = new QuickNavItem(true,
- new ItemData("leather_chestplate", 1, "tag:{display:{color:8991416}}"), "Wardrobe \\([12]/2\\)",
+ 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=\"}]}}}"),
+ "[minecraft:profile={id:[I;-2081424676,-57521078,-2073572414,158072763],name:\"\",properties:[{name:\"textures\",value:\"ewogICJ0aW1lc3RhbXAiIDogMTU5MTMxMDU4NTYwOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBhMDc3ZTI0OGQxNDI3NzJlYTgwMDg2NGY4YzU3OGI5ZDM2ODg1YjI5ZGFmODM2YjY0YTcwNjg4MmI2ZWMxMCIKICAgIH0KICB9Cn0=\"}]}]"),
"Sack of Sacks", "/sacks");
/* REGEX Explanation
@@ -44,17 +44,17 @@ public class QuickNavigationConfig {
@SerialEntry
public QuickNavItem button7 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}"),
+ "[minecraft:profile={id:[I;-300151517,-631415889,-1193921967,-1821784279],name:\"\",properties:[{name:\"textures\",value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}]"),
"none", "/hub");
@SerialEntry
public QuickNavItem button8 = new QuickNavItem(true, new ItemData("player_head", 1,
- "tag:{SkullOwner:{Id:[I;1605800870,415127827,-1236127084,15358548],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MWQ1YjI3M2ZmMGJjNTBjOTYwYjJjZDg2ZWVmMWM0MGExYjk0MDMyYWU3MWU3NTQ3NWE1NjhhODI1NzQyMSJ9fX0=\"}]}}}"),
+ "[minecraft:profile={id:[I;1605800870,415127827,-1236127084,15358548],name:\"\",properties:[{name:\"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=\"}]}}}"),
+ "[minecraft:profile={id:[I;-562285948,532499670,-1705302742,775653035],name:\"\",properties:[{name:\"textures\",value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjVkZjU1NTkyNjQzMGQ1ZDc1YWRlZDIxZGQ5NjE5Yjc2YzViN2NhMmM3ZjU0MDE0NDA1MjNkNTNhOGJjZmFhYiJ9fX0=\"}]}]"),
"Visit prtl", "/visit prtl");
@SerialEntry
@@ -68,73 +68,6 @@ public class QuickNavigationConfig {
@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");
-
- @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");
- }
-
public static class QuickNavItem {
public QuickNavItem(Boolean render, ItemData itemData, String uiTitle, String clickEvent) {
this.render = render;
@@ -157,16 +90,16 @@ public class QuickNavigationConfig {
}
public static class ItemData {
- public ItemData(String id, int count, String nbt) {
+ public ItemData(String id, int count, String components) {
this.id = id;
this.count = count;
- this.nbt = nbt;
+ this.components = components;
}
public ItemData(String id) {
this.id = id;
this.count = 1;
- this.nbt = "";
+ this.components = "[]";
}
@SerialEntry
@@ -176,6 +109,6 @@ public class QuickNavigationConfig {
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 9a20bfa8..e016988b 100644
--- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java
@@ -55,6 +55,9 @@ public class UIAndVisualsConfig {
public SearchOverlay searchOverlay = new SearchOverlay();
@SerialEntry
+ public InputCalculator inputCalculator = new InputCalculator();
+
+ @SerialEntry
public FlameOverlay flameOverlay = new FlameOverlay();
@SerialEntry
@@ -243,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;
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..97261c76
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigDataFixer.java
@@ -0,0 +1,90 @@
+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) {
+ long start = System.currentTimeMillis();
+
+ JsonObject newConfig = build().update(CONFIG_TYPE, new Dynamic<>(JsonOps.INSTANCE, oldConfig), JsonHelper.getInt(oldConfig, "version").orElse(1), SkyblockerConfigManager.CONFIG_VERSION).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));
+
+ 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..405a2781
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/config/datafixer/ConfigFix1.java
@@ -0,0 +1,227 @@
+package de.hysky.skyblocker.config.datafixer;
+
+import com.mojang.datafixers.DSL;
+import com.mojang.datafixers.DataFix;
+import com.mojang.datafixers.DataFixUtils;
+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 DataFix {
+ 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 <T> Dynamic<T> fixVersion(Dynamic<T> dynamic) {
+ return dynamic.set("version", dynamic.createInt(DataFixUtils.getVersion(getVersionKey())));
+ }
+
+ 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
+ .update("button1", ConfigFix1::fixQuickNavButton)
+ .update("button2", ConfigFix1::fixQuickNavButton)
+ .update("button3", ConfigFix1::fixQuickNavButton)
+ .update("button4", ConfigFix1::fixQuickNavButton)
+ .update("button5", ConfigFix1::fixQuickNavButton)
+ .update("button6", ConfigFix1::fixQuickNavButton)
+ .update("button7", ConfigFix1::fixQuickNavButton)
+ .update("button8", ConfigFix1::fixQuickNavButton)
+ .update("button9", ConfigFix1::fixQuickNavButton)
+ .update("button10", ConfigFix1::fixQuickNavButton)
+ .update("button11", ConfigFix1::fixQuickNavButton)
+ .update("button12", ConfigFix1::fixQuickNavButton));
+ }
+
+ 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/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/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..dd91314a 100644
--- a/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java
+++ b/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java
@@ -216,7 +216,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/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/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..a6adf66b 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNav.java
@@ -11,15 +11,15 @@ 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.text.Text;
import net.minecraft.util.Formatting;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
import java.util.regex.PatternSyntaxException;
public class QuickNav {
@@ -59,10 +59,9 @@ 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 += "}";
+ ItemStack stack = ItemStackComponentizationFixer.fromComponentsString(itemData.id, Math.clamp(itemData.count, 1, 99), itemData.components);
boolean uiTitleMatches = false;
+
try {
uiTitleMatches = screenTitle.matches(buttonInfo.uiTitle);
} catch (PatternSyntaxException e) {
@@ -75,6 +74,6 @@ public class QuickNav {
return new QuickNavButton(id,
uiTitleMatches,
buttonInfo.clickEvent,
- ItemStackComponentizationFixer.fixUpItem(StringNbtReader.parse(nbtString)));
+ stack);
}
}
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/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) {
diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json
index 3e1c817c..7da15ecc 100644
--- a/src/main/resources/assets/skyblocker/lang/en_us.json
+++ b/src/main/resources/assets/skyblocker/lang/en_us.json
@@ -89,10 +89,11 @@
"skyblocker.config.dungeons.dungeonScore.enableScoreHUD.deathMessagesNote": "\n\n\nNote: This only works correctly if death messages are enabled in your skyblock settings. If you want to hide death messages, use this mod's Hide Player Death Messages setting instead to allow further processing of death messages.",
"skyblocker.config.dungeons.dungeonScore.scoreScaling": "Score Scaling",
- "skyblocker.config.dungeons.map.enableMap": "Enable Map",
-
"skyblocker.config.dungeons.fancyPartyFinder": "Fancy Party Finder",
+ "skyblocker.config.dungeons.hideSoulweaverSkulls": "Hide Soulweaver Skulls",
+ "skyblocker.config.dungeons.hideSoulweaverSkulls.@Tooltip": "Hides the Haunted Skulls spawned that are spawned as a result of using Soulweaver Gloves.",
+
"skyblocker.config.dungeons.livid": "Livid (F5/M5)",
"skyblocker.config.dungeons.livid.enableLividColorGlow": "Enable Livid Color Glow",
"skyblocker.config.dungeons.livid.enableLividColorGlow.@Tooltip": "Applies the glowing effect to the correct Livid in F5/M5.",
@@ -104,6 +105,7 @@
"skyblocker.config.dungeons.livid.lividColorText.@Tooltip": "Text which will be sent in the chat during the Livid boss fight. The string \"[color]\" will be replaced with the livid color.",
"skyblocker.config.dungeons.map": "Map",
+ "skyblocker.config.dungeons.map.enableMap": "Enable Map",
"skyblocker.config.dungeons.map.mapScaling": "Map Scaling",
"skyblocker.config.dungeons.map.mapScreen": "Dungeon Map & Score Placement Config...",
@@ -168,6 +170,7 @@
"skyblocker.config.dungeons.starredMobGlow.@Tooltip": "Applies the glowing effect to starred mobs that are visible.\n\nWARNING: This feature is experimental and you may encounter issues with it.",
"skyblocker.config.dungeons.terminals": "Terminal Solvers (F7/M7)",
+ "skyblocker.config.dungeons.terminals.blockIncorrectClicks": "Block Incorrect Clicks",
"skyblocker.config.dungeons.terminals.solveColor": "Solve Select Colored",
"skyblocker.config.dungeons.terminals.solveOrder": "Solve Click In Order",
"skyblocker.config.dungeons.terminals.solveStartsWith": "Solve Starts With",
@@ -377,6 +380,22 @@
"skyblocker.config.mining": "Mining",
+ "skyblocker.config.mining.commissionWaypoints": "Commission Waypoints",
+ "skyblocker.config.mining.commissionWaypoints.mode": "Enable Commission Waypoints",
+ "skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[0]": "Off: Do not show Commission waypoint.",
+ "skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[1]": "\nDwarven: Show waypoints only in dwarven mines.",
+ "skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[2]": "\nGlacite: Show waypoints only in glacite tunnles.",
+ "skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[3]": "\nBoth: Show waypoints in dwarven mines and glacite tunnels.",
+ "skyblocker.config.mining.commissionWaypoints.mode.@Tooltip[4]": "\n(takes effect when commissions updated)",
+ "skyblocker.config.mining.commissionWaypoints.useColor": "Colored Waypoints",
+ "skyblocker.config.mining.commissionWaypoints.useColor.@Tooltip": "Color the waypoint text to match the block it's for.",
+ "skyblocker.config.mining.commissionWaypoints.textScale": "Text Scale",
+ "skyblocker.config.mining.commissionWaypoints.textScale.@Tooltip": "Scale the size of the commission labels.",
+ "skyblocker.config.mining.commissionWaypoints.showBaseCamp": "Show Basecamp Waypoint",
+ "skyblocker.config.mining.commissionWaypoints.showBaseCamp.@Tooltip": "Show waypoint for basecamp when in glacite tunnels (takes effect when commissions updated).",
+ "skyblocker.config.mining.commissionWaypoints.showEmissary": "Show Emissary",
+ "skyblocker.config.mining.commissionWaypoints.showEmissary.@Tooltip": "When a commission in the dwarven mines is finished show emissary locations (takes effect when commissions updated).",
+
"skyblocker.config.mining.crystalHollows": "Crystal Hollows",
"skyblocker.config.mining.crystalHollows.metalDetectorHelper": "Metal Detector Helper",
"skyblocker.config.mining.crystalHollows.metalDetectorHelper.@Tooltip": "Helper for the metal detector puzzle in the Mines of Divan.",
@@ -455,10 +474,10 @@
"skyblocker.config.quickNav": "Quick Navigation",
"skyblocker.config.quickNav.button": "Button %d",
"skyblocker.config.quickNav.button.clickEvent": "Click event",
+ "skyblocker.config.quickNav.button.item.components": "Item Components",
+ "skyblocker.config.quickNav.button.item.components.@Tooltip": "A string of item components enclosed in square brackets, which is the same format as the /give command.\n\nExample: [minecraft:enchantment_glint_override=true]",
"skyblocker.config.quickNav.button.item.count": "Item Count",
"skyblocker.config.quickNav.button.item.itemName": "Item ID",
- "skyblocker.config.quickNav.button.item.nbt": "NBT",
- "skyblocker.config.quickNav.button.item.nbt.@Tooltip": "\u00a7c\u00a7lWARNING: THIS MUST BE CONFIGURED WITH ITEM NBT NOT ITEM COMPONENTS! \n\n\u00a7fIn the future we will automatically migrate your config to use item components!",
"skyblocker.config.quickNav.button.render": "Render",
"skyblocker.config.quickNav.button.uiTitle": "UI Title",
"skyblocker.config.quickNav.enableQuickNav": "Enable Quick Navigation",
@@ -528,6 +547,13 @@
"skyblocker.config.uiAndVisuals.flameOverlay.flameOpacity": "Flame Opacity",
"skyblocker.config.uiAndVisuals.flameOverlay.flameOpacity.@Tooltip": "100% default opacity\n0% off",
+ "skyblocker.config.uiAndVisuals.inputCalculator": "Input Calculator",
+ "skyblocker.config.uiAndVisuals.inputCalculator.enabled": "Enable Sign Calculator",
+ "skyblocker.config.uiAndVisuals.inputCalculator.enabled.@Tooltip": "Enables the ability for you to do calculations when inputting values such as price for the ah.\n Key:\n S = 64\n E = 160\n K = 1,000\n M = 1,000,000\n B = 1,000,000,000\n\n purse/P = current purse value",
+ "skyblocker.config.uiAndVisuals.inputCalculator.requiresEquals": "Only show with \"=\".",
+ "skyblocker.config.uiAndVisuals.inputCalculator.requiresEquals.@Tooltip": "Only show the calculator when the message start with \"=\".",
+ "skyblocker.config.uiAndVisuals.inputCalculator.invalidEquation": "Invalid Equation",
+
"skyblocker.config.uiAndVisuals.itemCooldown": "Item Cooldown",
"skyblocker.config.uiAndVisuals.itemCooldown.enableItemCooldowns": "Enable Item Cooldown",
diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json
index 0032a557..828cc206 100644
--- a/src/main/resources/skyblocker.mixins.json
+++ b/src/main/resources/skyblocker.mixins.json
@@ -32,6 +32,7 @@
"PlayerSkinTextureMixin",
"RenderFishMixin",
"ScoreboardMixin",
+ "SignEditScreenMixin",
"SocialInteractionsPlayerListWidgetMixin",
"WindowMixin",
"WorldRendererMixin",