aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/utils')
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Utils.java11
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/container/ContainerMatcher.java20
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/container/ContainerSolver.java38
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/container/ContainerSolverManager.java154
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/container/RegexContainerMatcher.java68
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/container/SimpleContainerSolver.java38
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/container/SlotTextAdder.java30
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/container/TooltipAdder.java18
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/gui/AbstractContainerMatcher.java29
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolver.java52
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java157
11 files changed, 371 insertions, 244 deletions
diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java
index 042095d1..4de32710 100644
--- a/src/main/java/de/hysky/skyblocker/utils/Utils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java
@@ -3,6 +3,7 @@ package de.hysky.skyblocker.utils;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.util.UndashedUuid;
+import de.hysky.skyblocker.debug.Debug;
import de.hysky.skyblocker.events.SkyblockEvents;
import de.hysky.skyblocker.mixins.accessors.MessageHandlerAccessor;
import de.hysky.skyblocker.skyblock.item.MuseumItemCache;
@@ -17,7 +18,6 @@ import net.azureaaron.hmapi.network.packet.s2c.HelloS2CPacket;
import net.azureaaron.hmapi.network.packet.s2c.HypixelS2CPacket;
import net.azureaaron.hmapi.network.packet.v1.s2c.LocationUpdateS2CPacket;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
-import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.PlayerListEntry;
@@ -239,9 +239,8 @@ public class Utils {
public static void updatePlayerPresenceFromScoreboard(MinecraftClient client) {
List<String> sidebar = STRING_SCOREBOARD;
- FabricLoader fabricLoader = FabricLoader.getInstance();
if (client.world == null || client.isInSingleplayer() || sidebar.isEmpty()) {
- if (fabricLoader.isDevelopmentEnvironment()) {
+ if (Debug.debugEnabled()) {
sidebar = Collections.emptyList();
} else {
isOnSkyblock = false;
@@ -249,13 +248,13 @@ public class Utils {
}
}
- if (sidebar.isEmpty() && !fabricLoader.isDevelopmentEnvironment()) return;
+ if (sidebar.isEmpty() && !Debug.debugEnabled()) return;
- if (fabricLoader.isDevelopmentEnvironment() || isConnectedToHypixel(client)) {
+ if (Debug.debugEnabled() || isConnectedToHypixel(client)) {
if (!isOnHypixel) {
isOnHypixel = true;
}
- if (fabricLoader.isDevelopmentEnvironment() || sidebar.getFirst().contains("SKYBLOCK") || sidebar.getFirst().contains("SKIBLOCK")) {
+ if (Debug.debugEnabled() || sidebar.getFirst().contains("SKYBLOCK") || sidebar.getFirst().contains("SKIBLOCK")) {
if (!isOnSkyblock) {
if (!isInjected) {
isInjected = true;
diff --git a/src/main/java/de/hysky/skyblocker/utils/container/ContainerMatcher.java b/src/main/java/de/hysky/skyblocker/utils/container/ContainerMatcher.java
new file mode 100644
index 00000000..159f399e
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/container/ContainerMatcher.java
@@ -0,0 +1,20 @@
+package de.hysky.skyblocker.utils.container;
+
+import net.minecraft.client.gui.screen.Screen;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.function.Predicate;
+
+public interface ContainerMatcher extends Predicate<Screen> {
+ /**
+ * Tests if the given screen should be handled by this matcher.
+ * @return {@code true} if this matcher should apply to the given screen, {@code false} otherwise
+ */
+ @Override
+ boolean test(@NotNull Screen screen);
+
+ /**
+ * @return {@code true} if this matcher is enabled, {@code false} otherwise
+ */
+ boolean isEnabled();
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolver.java b/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolver.java
new file mode 100644
index 00000000..c6162049
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolver.java
@@ -0,0 +1,38 @@
+package de.hysky.skyblocker.utils.container;
+
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.utils.Resettable;
+import de.hysky.skyblocker.utils.render.gui.ColorHighlight;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
+import net.minecraft.item.ItemStack;
+
+import java.util.List;
+
+public interface ContainerSolver extends ContainerMatcher, Resettable {
+ List<ColorHighlight> getColors(Int2ObjectMap<ItemStack> slots);
+
+ default void start(GenericContainerScreen screen) {}
+
+ @Override
+ default void reset() {}
+
+ default boolean onClickSlot(int slot, ItemStack stack, int screenId) {
+ return false;
+ }
+
+ static void markHighlightsDirty() {
+ SkyblockerMod.getInstance().containerSolverManager.markDirty();
+ }
+
+ static void trimEdges(Int2ObjectMap<ItemStack> slots, int rows) {
+ for (int i = 0; i < rows; i++) {
+ slots.remove(9 * i);
+ slots.remove(9 * i + 8);
+ }
+ for (int i = 1; i < 8; i++) {
+ slots.remove(i);
+ slots.remove((rows - 1) * 9 + i);
+ }
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolverManager.java b/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolverManager.java
new file mode 100644
index 00000000..b67b9edf
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolverManager.java
@@ -0,0 +1,154 @@
+package de.hysky.skyblocker.utils.container;
+
+import com.mojang.blaze3d.systems.RenderSystem;
+import de.hysky.skyblocker.mixins.accessors.HandledScreenAccessor;
+import de.hysky.skyblocker.skyblock.accessories.newyearcakes.NewYearCakeBagHelper;
+import de.hysky.skyblocker.skyblock.accessories.newyearcakes.NewYearCakesHelper;
+import de.hysky.skyblocker.skyblock.bazaar.ReorderHelper;
+import de.hysky.skyblocker.skyblock.chocolatefactory.ChocolateFactorySolver;
+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.dwarven.CommissionHighlight;
+import de.hysky.skyblocker.skyblock.experiment.ChronomatronSolver;
+import de.hysky.skyblocker.skyblock.experiment.SuperpairsSolver;
+import de.hysky.skyblocker.skyblock.experiment.UltrasequencerSolver;
+import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.render.gui.ColorHighlight;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.item.ItemStack;
+import net.minecraft.screen.slot.Slot;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * Manager class for {@link SimpleContainerSolver}s like terminal solvers and experiment solvers. To add a new gui solver, extend {@link SimpleContainerSolver} and register it in {@link #ContainerSolverManager()}.
+ */
+public class ContainerSolverManager {
+ private final ContainerSolver[] solvers;
+ private ContainerSolver currentSolver = null;
+ private List<ColorHighlight> highlights;
+ /**
+ * Useful for keeping track of a solver's state in a Screen instance, such as if Hypixel closes & reopens a screen after every click (as they do with terminals).
+ */
+ private int screenId = 0;
+
+ public ContainerSolverManager() {
+ solvers = new ContainerSolver[]{
+ new ColorTerminal(),
+ new OrderTerminal(),
+ new StartsWithTerminal(),
+ new LightsOnTerminal(),
+ new CroesusHelper(),
+ new CroesusProfit(),
+ new ChronomatronSolver(),
+ new CommissionHighlight(),
+ new SuperpairsSolver(),
+ UltrasequencerSolver.INSTANCE,
+ new NewYearCakeBagHelper(),
+ NewYearCakesHelper.INSTANCE,
+ new ChocolateFactorySolver(),
+ new ReorderHelper()
+ };
+ }
+
+ public ContainerSolver getCurrentSolver() {
+ return currentSolver;
+ }
+
+ public void init() {
+ ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
+ if (Utils.isOnSkyblock() && screen instanceof GenericContainerScreen genericContainerScreen) {
+ ScreenEvents.afterRender(screen).register((screen1, context, mouseX, mouseY, delta) -> {
+ MatrixStack matrices = context.getMatrices();
+ matrices.push();
+ matrices.translate(((HandledScreenAccessor) genericContainerScreen).getX(), ((HandledScreenAccessor) genericContainerScreen).getY(), 300);
+ onDraw(context, genericContainerScreen.getScreenHandler().slots.subList(0, genericContainerScreen.getScreenHandler().getRows() * 9));
+ matrices.pop();
+ });
+ ScreenEvents.remove(screen).register(screen1 -> clearScreen());
+ onSetScreen(genericContainerScreen);
+ } else {
+ clearScreen();
+ }
+ });
+ }
+
+ public void onSetScreen(@NotNull GenericContainerScreen screen) {
+ String screenName = screen.getTitle().getString();
+ for (ContainerSolver solver : solvers) {
+ if (solver.isEnabled()) {
+ if (solver instanceof SimpleContainerSolver containerSolver && containerSolver.test(screenName)) {
+ ++screenId;
+ currentSolver = containerSolver;
+ currentSolver.start(screen);
+ markDirty();
+
+ return;
+ } else if (solver.test(screen)) {
+ ++screenId;
+ currentSolver = solver;
+ currentSolver.start(screen);
+ markDirty();
+
+ return;
+ }
+ }
+ }
+ clearScreen();
+ }
+
+ public void clearScreen() {
+ if (currentSolver != null) {
+ currentSolver.reset();
+ currentSolver = null;
+ }
+ }
+
+ public void markDirty() {
+ highlights = null;
+ }
+
+ /**
+ * @return Whether the click should be disallowed.
+ */
+ public boolean onSlotClick(int slot, ItemStack stack) {
+ if (currentSolver != null) {
+ return currentSolver.onClickSlot(slot, stack, screenId);
+ }
+
+ return false;
+ }
+
+ public void onDraw(DrawContext context, List<Slot> slots) {
+ if (currentSolver == null)
+ return;
+ if (highlights == null)
+ highlights = currentSolver.getColors(slotMap(slots));
+ RenderSystem.enableDepthTest();
+ RenderSystem.colorMask(true, true, true, false);
+ for (ColorHighlight highlight : highlights) {
+ Slot slot = slots.get(highlight.slot());
+ int color = highlight.color();
+ context.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, color);
+ }
+ RenderSystem.colorMask(true, true, true, true);
+ }
+
+ private Int2ObjectMap<ItemStack> slotMap(List<Slot> slots) {
+ Int2ObjectMap<ItemStack> slotMap = new Int2ObjectRBTreeMap<>();
+ for (int i = 0; i < slots.size(); i++) {
+ slotMap.put(i, slots.get(i).getStack());
+ }
+ return slotMap;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/container/RegexContainerMatcher.java b/src/main/java/de/hysky/skyblocker/utils/container/RegexContainerMatcher.java
new file mode 100644
index 00000000..4f9d49ae
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/container/RegexContainerMatcher.java
@@ -0,0 +1,68 @@
+package de.hysky.skyblocker.utils.container;
+
+import de.hysky.skyblocker.skyblock.ChestValue;
+import net.minecraft.client.gui.screen.Screen;
+import org.intellij.lang.annotations.Language;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A regex implementation of {@link ContainerMatcher} that matches the title of the screen.
+ */
+public abstract class RegexContainerMatcher implements ContainerMatcher {
+ /**
+ * The title of the screen must match this pattern for this to be applied. Null means it will be applied to all screens.
+ *
+ * @implNote Don't end your regex with a {@code $} as {@link ChestValue} appends text to the end of the title,
+ * so the regex will stop matching if the player uses chest value.
+ */
+ @Nullable
+ public final Pattern titlePattern;
+
+ @Nullable
+ public String[] groups = null;
+
+ @Override
+ public boolean test(@NotNull Screen screen) {
+ return test(screen.getTitle().getString());
+ }
+
+ public boolean test(@NotNull String title) {
+ if (titlePattern == null) return true;
+ Matcher matcher = titlePattern.matcher(title);
+ if (matcher.matches()) {
+ int groupCount = matcher.groupCount();
+ if (groupCount >= 1) { //No need to initialize the array if there are no groups
+ groups = new String[groupCount];
+ for (int i = 0; i < groupCount; i++) {
+ groups[i] = matcher.group(i + 1); // +1 because first group is the whole match, which is useless
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ protected RegexContainerMatcher() {
+ this((Pattern) null);
+ }
+
+ protected RegexContainerMatcher(@NotNull @Language("RegExp") String titlePattern) {
+ this(Pattern.compile(titlePattern));
+ }
+
+ protected RegexContainerMatcher(@Nullable Pattern titlePattern) {
+ this.titlePattern = titlePattern;
+ }
+
+ public @Nullable Pattern getTitlePattern() {
+ return titlePattern;
+ }
+
+ public final @Nullable String[] getGroups() {
+ return groups;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/container/SimpleContainerSolver.java b/src/main/java/de/hysky/skyblocker/utils/container/SimpleContainerSolver.java
new file mode 100644
index 00000000..7d8b7417
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/container/SimpleContainerSolver.java
@@ -0,0 +1,38 @@
+package de.hysky.skyblocker.utils.container;
+
+import org.intellij.lang.annotations.Language;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.regex.Pattern;
+
+/**
+ * Simple implementation of a container solver. Extend this class to add a new gui solver,
+ * like terminal solvers or experiment solvers and add it to {@link ContainerSolverManager#solvers}.
+ */
+public abstract class SimpleContainerSolver extends RegexContainerMatcher implements ContainerSolver {
+ /**
+ * Utility constructor that will compile the given string into a pattern.
+ *
+ * @see #SimpleContainerSolver(Pattern)
+ */
+ protected SimpleContainerSolver(@NotNull @Language("RegExp") String titlePattern) {
+ super(titlePattern);
+ }
+
+ /**
+ * Creates a ContainerSolver that will be applied to screens with titles that match the given pattern.
+ *
+ * @param titlePattern The pattern to match the screen title against.
+ */
+ protected SimpleContainerSolver(@NotNull Pattern titlePattern) {
+ super(titlePattern);
+ }
+
+ // A container solver that applies to every screen doesn't make sense,
+ // so we don't provide a constructor for that and force getTitlePattern to be @NotNull
+ @Override
+ public @NotNull Pattern getTitlePattern() {
+ assert super.getTitlePattern() != null;
+ return super.getTitlePattern();
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/container/SlotTextAdder.java b/src/main/java/de/hysky/skyblocker/utils/container/SlotTextAdder.java
new file mode 100644
index 00000000..72f92547
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/container/SlotTextAdder.java
@@ -0,0 +1,30 @@
+package de.hysky.skyblocker.utils.container;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.item.slottext.SlotText;
+import de.hysky.skyblocker.skyblock.item.slottext.SlotTextMode;
+import net.minecraft.item.ItemStack;
+import net.minecraft.screen.slot.Slot;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public interface SlotTextAdder extends ContainerMatcher {
+
+ /**
+ * This method will be called for each rendered slot. Consider using a switch statement on {@code slotId} if you wish to limit the text to specific slots.
+ *
+ * @return A list of positioned text to be rendered. Return {@link List#of()} if no text should be rendered.
+ * @implNote By minecraft's design, scaled text inexplicably moves around.
+ * It's also not anti-aliased, so it looks horribly jagged and unreadable when scaled down too much.
+ * So, limit your text to 3 characters (or roughly less than 20 width) if you want it to not look horrible.
+ */
+ @NotNull
+ List<SlotText> getText(@Nullable Slot slot, @NotNull ItemStack stack, int slotId);
+
+ @Override
+ default boolean isEnabled() {
+ return SkyblockerConfigManager.get().general.itemInfoDisplay.slotTextMode != SlotTextMode.DISABLED;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/container/TooltipAdder.java b/src/main/java/de/hysky/skyblocker/utils/container/TooltipAdder.java
new file mode 100644
index 00000000..2ff3fdf1
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/container/TooltipAdder.java
@@ -0,0 +1,18 @@
+package de.hysky.skyblocker.utils.container;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.screen.slot.Slot;
+import net.minecraft.text.Text;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public interface TooltipAdder extends ContainerMatcher {
+ /**
+ * @implNote The first element of the lines list holds the item's display name,
+ * as it's a list of all lines that will be displayed in the tooltip.
+ */
+ void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List<Text> lines);
+
+ int getPriority();
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/render/gui/AbstractContainerMatcher.java b/src/main/java/de/hysky/skyblocker/utils/render/gui/AbstractContainerMatcher.java
deleted file mode 100644
index bf255218..00000000
--- a/src/main/java/de/hysky/skyblocker/utils/render/gui/AbstractContainerMatcher.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package de.hysky.skyblocker.utils.render.gui;
-
-import de.hysky.skyblocker.skyblock.ChestValue;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.regex.Pattern;
-
-public abstract class AbstractContainerMatcher {
- /**
- * The title of the screen must match this pattern for this to be applied. Null means it will be applied to all screens.
- * @implNote Don't end your regex with a {@code $} as {@link ChestValue} appends text to the end of the title,
- * so the regex will stop matching if the player uses chest value.
- */
- @Nullable
- public final Pattern titlePattern;
-
- protected AbstractContainerMatcher() {
- this((Pattern) null);
- }
-
- protected AbstractContainerMatcher(@NotNull String titlePattern) {
- this(Pattern.compile(titlePattern));
- }
-
- protected AbstractContainerMatcher(@Nullable Pattern titlePattern) {
- this.titlePattern = titlePattern;
- }
-}
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
deleted file mode 100644
index 9a9d0907..00000000
--- a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolver.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package de.hysky.skyblocker.utils.render.gui;
-
-import de.hysky.skyblocker.SkyblockerMod;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
-import net.minecraft.item.ItemStack;
-import org.intellij.lang.annotations.Language;
-
-import java.util.List;
-import java.util.regex.Pattern;
-
-/**
- * Abstract class for gui solvers. Extend this class to add a new gui solver, like terminal solvers or experiment solvers.
- */
-public abstract class ContainerSolver extends AbstractContainerMatcher {
- protected ContainerSolver(@Language("RegExp") String titlePattern) {
- super(titlePattern);
- }
-
- protected abstract boolean isEnabled();
-
- public final Pattern getName() {
- return titlePattern;
- }
-
- protected void start(GenericContainerScreen screen) {
- }
-
- protected void reset() {
- }
-
- protected void markHighlightsDirty() {
- SkyblockerMod.getInstance().containerSolverManager.markDirty();
- }
-
- protected boolean onClickSlot(int slot, ItemStack stack, int screenId, String[] groups) {
- return false;
- }
-
- protected abstract List<ColorHighlight> getColors(String[] groups, Int2ObjectMap<ItemStack> slots);
-
- 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);
- }
- for (int i = 1; i < 8; i++) {
- slots.remove(i);
- slots.remove((rows - 1) * 9 + i);
- }
- }
-}
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
deleted file mode 100644
index 79cc78f5..00000000
--- a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package de.hysky.skyblocker.utils.render.gui;
-
-import com.mojang.blaze3d.systems.RenderSystem;
-import de.hysky.skyblocker.mixins.accessors.HandledScreenAccessor;
-import de.hysky.skyblocker.skyblock.accessories.newyearcakes.NewYearCakeBagHelper;
-import de.hysky.skyblocker.skyblock.accessories.newyearcakes.NewYearCakesHelper;
-import de.hysky.skyblocker.skyblock.bazaar.ReorderHelper;
-import de.hysky.skyblocker.skyblock.chocolatefactory.ChocolateFactorySolver;
-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.dwarven.CommissionHighlight;
-import de.hysky.skyblocker.skyblock.experiment.ChronomatronSolver;
-import de.hysky.skyblocker.skyblock.experiment.SuperpairsSolver;
-import de.hysky.skyblocker.skyblock.experiment.UltrasequencerSolver;
-import de.hysky.skyblocker.utils.Utils;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap;
-import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
-import net.minecraft.client.util.math.MatrixStack;
-import net.minecraft.item.ItemStack;
-import net.minecraft.screen.slot.Slot;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Manager class for {@link ContainerSolver}s like terminal solvers and experiment solvers. To add a new gui solver, extend {@link ContainerSolver} and register it in {@link #ContainerSolverManager()}.
- */
-public class ContainerSolverManager {
- private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("");
- private final ContainerSolver[] solvers;
- private ContainerSolver currentSolver = null;
- private String[] groups;
- private List<ColorHighlight> highlights;
- /**
- * Useful for keeping track of a solver's state in a Screen instance, such as if Hypixel closes & reopens a screen after every click (as they do with terminals).
- */
- private int screenId = 0;
-
- public ContainerSolverManager() {
- solvers = new ContainerSolver[]{
- new ColorTerminal(),
- new OrderTerminal(),
- new StartsWithTerminal(),
- new LightsOnTerminal(),
- new CroesusHelper(),
- new CommissionHighlight(),
- new CroesusProfit(),
- new ChronomatronSolver(),
- new SuperpairsSolver(),
- UltrasequencerSolver.INSTANCE,
- new NewYearCakeBagHelper(),
- NewYearCakesHelper.INSTANCE,
- new ChocolateFactorySolver(),
- new ReorderHelper()
- };
- }
-
- public ContainerSolver getCurrentSolver() {
- return currentSolver;
- }
-
- public void init() {
- ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
- if (Utils.isOnSkyblock() && screen instanceof GenericContainerScreen genericContainerScreen) {
- ScreenEvents.afterRender(screen).register((screen1, context, mouseX, mouseY, delta) -> {
- MatrixStack matrices = context.getMatrices();
- matrices.push();
- matrices.translate(((HandledScreenAccessor) genericContainerScreen).getX(), ((HandledScreenAccessor) genericContainerScreen).getY(), 300);
- onDraw(context, genericContainerScreen.getScreenHandler().slots.subList(0, genericContainerScreen.getScreenHandler().getRows() * 9));
- matrices.pop();
- });
- ScreenEvents.remove(screen).register(screen1 -> clearScreen());
- onSetScreen(genericContainerScreen);
- } else {
- clearScreen();
- }
- });
- }
-
- public void onSetScreen(@NotNull GenericContainerScreen screen) {
- String screenName = screen.getTitle().getString();
- Matcher matcher = PLACEHOLDER_PATTERN.matcher(screenName);
- for (ContainerSolver solver : solvers) {
- if (solver.isEnabled()) {
- matcher.usePattern(solver.getName());
- matcher.reset();
- if (matcher.matches()) {
- ++screenId;
- currentSolver = solver;
- groups = new String[matcher.groupCount()];
- for (int i = 0; i < groups.length; i++) {
- groups[i] = matcher.group(i + 1);
- }
- currentSolver.start(screen);
- markDirty();
-
- return;
- }
- }
- }
- clearScreen();
- }
-
- public void clearScreen() {
- if (currentSolver != null) {
- currentSolver.reset();
- currentSolver = null;
- }
- }
-
- public void markDirty() {
- highlights = null;
- }
-
- /**
- * @return Whether the click should be disallowed.
- */
- public boolean onSlotClick(int slot, ItemStack stack) {
- if (currentSolver != null) {
- return currentSolver.onClickSlot(slot, stack, screenId, groups);
- }
-
- return false;
- }
-
- public void onDraw(DrawContext context, List<Slot> slots) {
- if (currentSolver == null)
- return;
- if (highlights == null)
- highlights = currentSolver.getColors(groups, slotMap(slots));
- RenderSystem.enableDepthTest();
- RenderSystem.colorMask(true, true, true, false);
- for (ColorHighlight highlight : highlights) {
- Slot slot = slots.get(highlight.slot());
- int color = highlight.color();
- context.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, color);
- }
- RenderSystem.colorMask(true, true, true, true);
- }
-
- private Int2ObjectMap<ItemStack> slotMap(List<Slot> slots) {
- Int2ObjectMap<ItemStack> slotMap = new Int2ObjectRBTreeMap<>();
- for (int i = 0; i < slots.size(); i++) {
- slotMap.put(i, slots.get(i).getStack());
- }
- return slotMap;
- }
-}