aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorKevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>2023-06-16 16:34:16 +0800
committerKevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>2023-06-24 12:57:16 +0800
commit4a1075ce0e7c7bb53179820c44f639ce79fe7404 (patch)
tree6f1827da95d5718095236c423a9f3b155d2795dd /src/main/java
parent579feae3e4a2231bf7e6f98977762bf38b762f3b (diff)
downloadSkyblocker-4a1075ce0e7c7bb53179820c44f639ce79fe7404.tar.gz
Skyblocker-4a1075ce0e7c7bb53179820c44f639ce79fe7404.tar.bz2
Skyblocker-4a1075ce0e7c7bb53179820c44f639ce79fe7404.zip
Add Chronomatron Solver
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java10
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/gui/ColorHighlight.java15
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/gui/ContainerSolver.java21
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/gui/ContainerSolverManager.java20
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java45
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/ChronomatronSolver.java126
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/ExperimentSolver.java59
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/SuperpairsSolver.java44
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/UltrasequencerSolver.java40
13 files changed, 378 insertions, 18 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
index 31887a90..5621a258 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java
@@ -146,6 +146,10 @@ public class SkyblockerConfig implements ConfigData {
@ConfigEntry.Gui.CollapsibleObject()
public Bars bars = new Bars();
+ @ConfigEntry.Category("experiments")
+ @ConfigEntry.Gui.CollapsibleObject()
+ public Experiments experiments = new Experiments();
+
@ConfigEntry.Category("fishing")
@ConfigEntry.Gui.CollapsibleObject()
public Fishing fishing = new Fishing();
@@ -219,6 +223,12 @@ public class SkyblockerConfig implements ConfigData {
}
}
+ public static class Experiments {
+ public boolean enableChronomatronSolver = true;
+ public boolean enableSuperpairsSolver = true;
+ public boolean enableUltrasequencerSolver = true;
+ }
+
public static class Fishing {
public boolean enableFishingHelper = true;
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/gui/ColorHighlight.java b/src/main/java/me/xmrvizzy/skyblocker/gui/ColorHighlight.java
index 5120ceac..d0bd68ae 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/gui/ColorHighlight.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/gui/ColorHighlight.java
@@ -1,4 +1,19 @@
package me.xmrvizzy.skyblocker.gui;
public record ColorHighlight(int slot, int color) {
+ public static ColorHighlight red(int slot) {
+ return new ColorHighlight(slot, ContainerSolver.RED_HIGHLIGHT);
+ }
+
+ public static ColorHighlight yellow(int slot) {
+ return new ColorHighlight(slot, ContainerSolver.YELLOW_HIGHLIGHT);
+ }
+
+ public static ColorHighlight green(int slot) {
+ return new ColorHighlight(slot, ContainerSolver.GREEN_HIGHLIGHT);
+ }
+
+ public static ColorHighlight gray(int slot) {
+ return new ColorHighlight(slot, ContainerSolver.GRAY_HIGHLIGHT);
+ }
} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/gui/ContainerSolver.java b/src/main/java/me/xmrvizzy/skyblocker/gui/ContainerSolver.java
index 84de64eb..e52855a2 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/gui/ContainerSolver.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/gui/ContainerSolver.java
@@ -1,5 +1,6 @@
package me.xmrvizzy.skyblocker.gui;
+import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
import net.minecraft.item.ItemStack;
import java.util.List;
@@ -11,22 +12,30 @@ import java.util.regex.Pattern;
*/
public abstract class ContainerSolver {
private final Pattern CONTAINER_NAME;
- protected final static int GREEN_HIGHLIGHT = 128 << 24 | 64 << 16 | 196 << 8 | 64;
- protected final static int GRAY_HIGHLIGHT = 128 << 24 | 64 << 16 | 64 << 8 | 64;
+ protected static final int RED_HIGHLIGHT = 64 << 24 | 255 << 16;
+ protected static final int YELLOW_HIGHLIGHT = 128 << 24 | 255 << 16 | 255 << 8;
+ protected static final int GREEN_HIGHLIGHT = 128 << 24 | 64 << 16 | 196 << 8 | 64;
+ protected static final int GRAY_HIGHLIGHT = 128 << 24 | 64 << 16 | 64 << 8 | 64;
- public ContainerSolver(String containerName) {
+ protected ContainerSolver(String containerName) {
CONTAINER_NAME = Pattern.compile(containerName);
}
- public abstract boolean isEnabled();
+ protected abstract boolean isEnabled();
public Pattern getName() {
return CONTAINER_NAME;
}
- public abstract List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots);
+ protected void start(GenericContainerScreen screen) {
+ }
+
+ protected void reset() {
+ }
+
+ protected abstract List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots);
- public void trimEdges(Map<Integer, ItemStack> slots, int rows) {
+ protected void trimEdges(Map<Integer, 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/me/xmrvizzy/skyblocker/gui/ContainerSolverManager.java b/src/main/java/me/xmrvizzy/skyblocker/gui/ContainerSolverManager.java
index 354e7e3a..43bf32d7 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/gui/ContainerSolverManager.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/gui/ContainerSolverManager.java
@@ -6,6 +6,9 @@ import me.xmrvizzy.skyblocker.skyblock.dungeon.CroesusHelper;
import me.xmrvizzy.skyblocker.skyblock.dungeon.terminal.ColorTerminal;
import me.xmrvizzy.skyblocker.skyblock.dungeon.terminal.OrderTerminal;
import me.xmrvizzy.skyblocker.skyblock.dungeon.terminal.StartsWithTerminal;
+import me.xmrvizzy.skyblocker.skyblock.experiment.ChronomatronSolver;
+import me.xmrvizzy.skyblocker.skyblock.experiment.SuperpairsSolver;
+import me.xmrvizzy.skyblocker.skyblock.experiment.UltrasequencerSolver;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.minecraft.client.gui.DrawContext;
@@ -36,10 +39,17 @@ public class ContainerSolverManager {
new ColorTerminal(),
new OrderTerminal(),
new StartsWithTerminal(),
- new CroesusHelper()
+ new CroesusHelper(),
+ new ChronomatronSolver(),
+ new SuperpairsSolver(),
+ new UltrasequencerSolver()
};
}
+ public ContainerSolver getCurrentSolver() {
+ return currentSolver;
+ }
+
public void init() {
ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
if (Utils.isOnSkyblock() && screen instanceof GenericContainerScreen genericContainerScreen) {
@@ -50,6 +60,7 @@ public class ContainerSolverManager {
onDraw(context, genericContainerScreen.getScreenHandler().slots.subList(0, genericContainerScreen.getScreenHandler().getRows() * 9));
matrices.pop();
});
+ ScreenEvents.remove(screen).register(screen1 -> clearScreen());
onSetScreen(genericContainerScreen);
} else {
clearScreen();
@@ -67,16 +78,19 @@ public class ContainerSolverManager {
if (matcher.matches()) {
currentSolver = solver;
groups = new String[matcher.groupCount()];
- for (int i = 0; i < groups.length; i++)
+ for (int i = 0; i < groups.length; i++) {
groups[i] = matcher.group(i + 1);
+ }
+ currentSolver.start(screen);
return;
}
}
}
- currentSolver = null;
+ clearScreen();
}
public void clearScreen() {
+ currentSolver.reset();
currentSolver = null;
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java
index 2638db7e..b8df488c 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java
@@ -1,19 +1,27 @@
package me.xmrvizzy.skyblocker.mixin;
+import me.xmrvizzy.skyblocker.SkyblockerMod;
import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.gui.ContainerSolver;
import me.xmrvizzy.skyblocker.skyblock.BackpackPreview;
+import me.xmrvizzy.skyblocker.skyblock.experiment.ChronomatronSolver;
+import me.xmrvizzy.skyblocker.skyblock.experiment.ExperimentSolver;
+import me.xmrvizzy.skyblocker.skyblock.experiment.SuperpairsSolver;
+import me.xmrvizzy.skyblocker.skyblock.experiment.UltrasequencerSolver;
import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.screen.slot.Slot;
+import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.text.Text;
import org.jetbrains.annotations.Nullable;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@@ -44,7 +52,7 @@ public abstract class HandledScreenMixin extends Screen {
String strName = stackName.getString();
if(Utils.isOnSkyblock() && SkyblockerConfig.get().general.hideEmptyTooltips && strName.equals(" ")) ci.cancel();
}
-
+
//Backpack Preview
String title = this.getTitle().getString();
boolean shiftDown = SkyblockerConfig.get().general.backpackPreviewWithoutShift ^ Screen.hasShiftDown();
@@ -53,4 +61,39 @@ public abstract class HandledScreenMixin extends Screen {
if (BackpackPreview.renderPreview(context, this.focusedSlot.getIndex(), x, y)) ci.cancel();
}
}
+
+ @Redirect(method = {"drawSlot", "drawMouseoverTooltip"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/slot/Slot;getStack()Lnet/minecraft/item/ItemStack;", ordinal = 0))
+ private ItemStack skyblocker$experimentSolvers$getStack(Slot slot) {
+ ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver();
+ if ((currentSolver instanceof SuperpairsSolver || currentSolver instanceof UltrasequencerSolver) && ((ExperimentSolver) currentSolver).getState() == ExperimentSolver.State.SHOW && slot.inventory instanceof SimpleInventory) {
+ ItemStack itemStack = ((ExperimentSolver) currentSolver).getSlots().get(slot.getIndex());
+ return itemStack == null ? slot.getStack() : itemStack;
+ }
+ return slot.getStack();
+ }
+
+ @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;clickSlot(IIILnet/minecraft/screen/slot/SlotActionType;Lnet/minecraft/entity/player/PlayerEntity;)V"))
+ private void skyblockmod_onSlotClick(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) {
+ if (slot != null) {
+ ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver();
+ if (currentSolver instanceof ExperimentSolver experimentSolver && experimentSolver.getState() == ExperimentSolver.State.SHOW && slot.inventory instanceof SimpleInventory) {
+ if (currentSolver instanceof ChronomatronSolver chronomatronSolver) {
+ Item item = chronomatronSolver.getChronomatronSlots().get(chronomatronSolver.getChronomatronCurrentOrdinal());
+ if (slot.getStack().isOf(item) || ChronomatronSolver.TERRACOTTA_TO_GLASS.get(slot.getStack().getItem()) == item) {
+ if (chronomatronSolver.incrementChronomatronCurrentOrdinal() >= chronomatronSolver.getChronomatronSlots().size()) {
+ chronomatronSolver.setState(ExperimentSolver.State.END);
+ }
+ }
+ } else if (currentSolver instanceof SuperpairsSolver superpairsSolver) {
+ superpairsSolver.setSuperpairsPrevClickedSlot(slot.getIndex());
+ superpairsSolver.setSuperpairsCurrentSlot(ItemStack.EMPTY);
+ } else if (currentSolver instanceof UltrasequencerSolver ultrasequencerSolver) {
+ if (slot.getIndex() == ultrasequencerSolver.getUltrasequencerNextSlot()) {
+ int count = ultrasequencerSolver.getSlots().get(ultrasequencerSolver.getUltrasequencerNextSlot()).getCount() + 1;
+ ultrasequencerSolver.getSlots().entrySet().stream().filter(entry -> entry.getValue().getCount() == count).findAny().ifPresentOrElse((entry) -> ultrasequencerSolver.setUltrasequencerNextSlot(entry.getKey()), () -> ultrasequencerSolver.setState(ExperimentSolver.State.END));
+ }
+ }
+ }
+ }
+ }
}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java
index ec3655f0..5e7ca95f 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java
@@ -14,12 +14,12 @@ public class CroesusHelper extends ContainerSolver {
public CroesusHelper() { super("^Croesus$"); }
@Override
- public boolean isEnabled() {
+ protected boolean isEnabled() {
return SkyblockerConfig.get().locations.dungeons.croesusHelper;
}
@Override
- public List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
+ protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
List<ColorHighlight> highlights = new ArrayList<>();
for (Map.Entry<Integer, ItemStack> entry : slots.entrySet()) {
ItemStack stack = entry.getValue();
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java
index 0bfc0d60..30376254 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/ColorTerminal.java
@@ -27,13 +27,13 @@ public class ColorTerminal extends ContainerSolver {
}
@Override
- public boolean isEnabled() {
+ protected boolean isEnabled() {
targetColor = null;
return SkyblockerConfig.get().locations.dungeons.terminals.solveColor;
}
@Override
- public List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
+ protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
trimEdges(slots, 6);
List<ColorHighlight> highlights = new ArrayList<>();
String colorString = groups[0];
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java
index 1cf0dcfc..3b4e1c50 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/OrderTerminal.java
@@ -21,14 +21,14 @@ public class OrderTerminal extends ContainerSolver {
}
@Override
- public boolean isEnabled() {
+ protected boolean isEnabled() {
orderedSlots = null;
currentNum = 0;
return SkyblockerConfig.get().locations.dungeons.terminals.solveOrder;
}
@Override
- public List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
+ protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
if(orderedSlots == null && !orderSlots(slots))
return Collections.emptyList();
while(currentNum < PANES_NUM && Items.LIME_STAINED_GLASS_PANE.equals(slots.get(orderedSlots[currentNum]).getItem()))
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java
index 26d2a2c4..a836a679 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/terminal/StartsWithTerminal.java
@@ -15,12 +15,12 @@ public class StartsWithTerminal extends ContainerSolver {
}
@Override
- public boolean isEnabled() {
+ protected boolean isEnabled() {
return SkyblockerConfig.get().locations.dungeons.terminals.solveStartsWith;
}
@Override
- public List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
+ protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
trimEdges(slots, 6);
String prefix = groups[0];
List<ColorHighlight> highlights = new ArrayList<>();
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/ChronomatronSolver.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/ChronomatronSolver.java
new file mode 100644
index 00000000..ee88b98f
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/ChronomatronSolver.java
@@ -0,0 +1,126 @@
+package me.xmrvizzy.skyblocker.skyblock.experiment;
+
+import com.google.common.collect.ImmutableMap;
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.gui.ColorHighlight;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
+import net.minecraft.inventory.Inventory;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class ChronomatronSolver extends ExperimentSolver {
+ public static final ImmutableMap<Item, Item> TERRACOTTA_TO_GLASS = ImmutableMap.ofEntries(
+ new AbstractMap.SimpleImmutableEntry<>(Items.RED_TERRACOTTA, Items.RED_STAINED_GLASS),
+ new AbstractMap.SimpleImmutableEntry<>(Items.ORANGE_TERRACOTTA, Items.ORANGE_STAINED_GLASS),
+ new AbstractMap.SimpleImmutableEntry<>(Items.YELLOW_TERRACOTTA, Items.YELLOW_STAINED_GLASS),
+ new AbstractMap.SimpleImmutableEntry<>(Items.LIME_TERRACOTTA, Items.LIME_STAINED_GLASS),
+ new AbstractMap.SimpleImmutableEntry<>(Items.GREEN_TERRACOTTA, Items.GREEN_STAINED_GLASS),
+ new AbstractMap.SimpleImmutableEntry<>(Items.CYAN_TERRACOTTA, Items.CYAN_STAINED_GLASS),
+ new AbstractMap.SimpleImmutableEntry<>(Items.LIGHT_BLUE_TERRACOTTA, Items.LIGHT_BLUE_STAINED_GLASS),
+ new AbstractMap.SimpleImmutableEntry<>(Items.BLUE_TERRACOTTA, Items.BLUE_STAINED_GLASS),
+ new AbstractMap.SimpleImmutableEntry<>(Items.PURPLE_TERRACOTTA, Items.PURPLE_STAINED_GLASS),
+ new AbstractMap.SimpleImmutableEntry<>(Items.PINK_TERRACOTTA, Items.PINK_STAINED_GLASS)
+ );
+
+ private final List<Item> chronomatronSlots = new ArrayList<>();
+ private int chronomatronChainLengthCount;
+ private int chronomatronCurrentSlot;
+ private int chronomatronCurrentOrdinal;
+
+ public ChronomatronSolver() {
+ super("^Chronomatron \\(");
+ }
+
+ public List<Item> getChronomatronSlots() {
+ return chronomatronSlots;
+ }
+
+ public int getChronomatronCurrentOrdinal() {
+ return chronomatronCurrentOrdinal;
+ }
+
+ public int incrementChronomatronCurrentOrdinal() {
+ return ++chronomatronCurrentOrdinal;
+ }
+
+ @Override
+ protected boolean isEnabled(SkyblockerConfig.Experiments experimentsConfig) {
+ return experimentsConfig.enableChronomatronSolver;
+ }
+
+ @Override
+ protected void tick(Screen screen) {
+ if (isEnabled() && screen instanceof GenericContainerScreen genericContainerScreen && genericContainerScreen.getTitle().getString().startsWith("Chronomatron (")) {
+ switch (state) {
+ case REMEMBER -> {
+ Inventory inventory = genericContainerScreen.getScreenHandler().getInventory();
+ if (chronomatronCurrentSlot == 0) {
+ for (int index = 10; index < 43; index++) {
+ if (inventory.getStack(index).hasEnchantments()) {
+ if (chronomatronSlots.size() <= chronomatronChainLengthCount) {
+ chronomatronSlots.add(TERRACOTTA_TO_GLASS.get(inventory.getStack(index).getItem()));
+ state = State.WAIT;
+ } else {
+ chronomatronChainLengthCount++;
+ }
+ chronomatronCurrentSlot = index;
+ return;
+ }
+ }
+ } else if (!inventory.getStack(chronomatronCurrentSlot).hasEnchantments()) {
+ chronomatronCurrentSlot = 0;
+ }
+ }
+ case WAIT -> {
+ if (genericContainerScreen.getScreenHandler().getInventory().getStack(49).getName().getString().startsWith("Timer: ")) {
+ state = State.SHOW;
+ }
+ }
+ case END -> {
+ String name = genericContainerScreen.getScreenHandler().getInventory().getStack(49).getName().getString();
+ if (!name.startsWith("Timer: ")) {
+ if (name.equals("Remember the pattern!")) {
+ chronomatronChainLengthCount = 0;
+ chronomatronCurrentOrdinal = 0;
+ state = State.REMEMBER;
+ } else {
+ reset();
+ }
+ }
+ }
+ }
+ } else {
+ reset();
+ }
+ }
+
+ @Override
+ protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
+ List<ColorHighlight> highlights = new ArrayList<>();
+ for (Map.Entry<Integer, ItemStack> indexStack : slots.entrySet()) {
+ int index = indexStack.getKey();
+ ItemStack stack = indexStack.getValue();
+ Item item = chronomatronSlots.get(chronomatronCurrentOrdinal);
+ if (stack.isOf(item) || TERRACOTTA_TO_GLASS.get(stack.getItem()) == item) {
+ highlights.add(ColorHighlight.green(index));
+ }
+ }
+ return highlights;
+ }
+
+ @Override
+ protected void reset() {
+ super.reset();
+ chronomatronSlots.clear();
+ chronomatronChainLengthCount = 0;
+ chronomatronCurrentSlot = 0;
+ chronomatronCurrentOrdinal = 0;
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/ExperimentSolver.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/ExperimentSolver.java
new file mode 100644
index 00000000..91eabcfe
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/ExperimentSolver.java
@@ -0,0 +1,59 @@
+package me.xmrvizzy.skyblocker.skyblock.experiment;
+
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.gui.ContainerSolver;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
+import net.minecraft.item.ItemStack;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class ExperimentSolver extends ContainerSolver {
+ public enum State {
+ REMEMBER, WAIT, SHOW, END
+ }
+
+ protected State state = State.REMEMBER;
+ protected final Map<Integer, ItemStack> slots = new HashMap<>();
+
+ protected ExperimentSolver(String containerName) {
+ super(containerName);
+ }
+
+ public State getState() {
+ return state;
+ }
+
+ public void setState(State state) {
+ this.state = state;
+ }
+
+ public Map<Integer, ItemStack> getSlots() {
+ return slots;
+ }
+
+ @Override
+ protected final boolean isEnabled() {
+ return isEnabled(SkyblockerConfig.get().general.experiments);
+ }
+
+ protected abstract boolean isEnabled(SkyblockerConfig.Experiments experimentsConfig);
+
+ @Override
+ protected void start(GenericContainerScreen screen) {
+ super.start(screen);
+ state = State.REMEMBER;
+ ScreenEvents.afterTick(screen).register(this::tick);
+ }
+
+ @Override
+ protected void reset() {
+ super.reset();
+ state = State.REMEMBER;
+ slots.clear();
+ }
+
+ protected abstract void tick(Screen screen);
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/SuperpairsSolver.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/SuperpairsSolver.java
new file mode 100644
index 00000000..5a5993bc
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/SuperpairsSolver.java
@@ -0,0 +1,44 @@
+package me.xmrvizzy.skyblocker.skyblock.experiment;
+
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.gui.ColorHighlight;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.item.ItemStack;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class SuperpairsSolver extends ExperimentSolver {
+ private int superpairsPrevClickedSlot;
+ private ItemStack superpairsCurrentSlot;
+ private final Set<Integer> superpairsDuplicatedSlots = new HashSet<>();
+
+ public SuperpairsSolver() {
+ super("^Superpairs \\(");
+ }
+
+ public void setSuperpairsPrevClickedSlot(int superpairsPrevClickedSlot) {
+ this.superpairsPrevClickedSlot = superpairsPrevClickedSlot;
+ }
+
+ public void setSuperpairsCurrentSlot(ItemStack superpairsCurrentSlot) {
+ this.superpairsCurrentSlot = superpairsCurrentSlot;
+ }
+
+ @Override
+ protected boolean isEnabled(SkyblockerConfig.Experiments experimentsConfig) {
+ return experimentsConfig.enableSuperpairsSolver;
+ }
+
+ @Override
+ protected void tick(Screen screen) {
+
+ }
+
+ @Override
+ protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
+ return null;
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/UltrasequencerSolver.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/UltrasequencerSolver.java
new file mode 100644
index 00000000..8ea44bce
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/UltrasequencerSolver.java
@@ -0,0 +1,40 @@
+package me.xmrvizzy.skyblocker.skyblock.experiment;
+
+import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
+import me.xmrvizzy.skyblocker.gui.ColorHighlight;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.item.ItemStack;
+
+import java.util.List;
+import java.util.Map;
+
+public class UltrasequencerSolver extends ExperimentSolver {
+ private int ultrasequencerNextSlot;
+
+ public UltrasequencerSolver() {
+ super("^Ultrasequencer \\(");
+ }
+
+ public int getUltrasequencerNextSlot() {
+ return ultrasequencerNextSlot;
+ }
+
+ public void setUltrasequencerNextSlot(int ultrasequencerNextSlot) {
+ this.ultrasequencerNextSlot = ultrasequencerNextSlot;
+ }
+
+ @Override
+ protected boolean isEnabled(SkyblockerConfig.Experiments experimentsConfig) {
+ return experimentsConfig.enableUltrasequencerSolver;
+ }
+
+ @Override
+ protected void tick(Screen screen) {
+
+ }
+
+ @Override
+ protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) {
+ return null;
+ }
+}