diff options
Diffstat (limited to 'src/main/java')
13 files changed, 500 insertions, 50 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..4367e6e7 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/gui/ColorHighlight.java +++ b/src/main/java/me/xmrvizzy/skyblocker/gui/ColorHighlight.java @@ -1,4 +1,24 @@ package me.xmrvizzy.skyblocker.gui; public record ColorHighlight(int slot, int color) { + private static final int RED_HIGHLIGHT = 64 << 24 | 255 << 16; + private static final int YELLOW_HIGHLIGHT = 128 << 24 | 255 << 16 | 255 << 8; + private static final int GREEN_HIGHLIGHT = 128 << 24 | 64 << 16 | 196 << 8 | 64; + private static final int GRAY_HIGHLIGHT = 128 << 24 | 64 << 16 | 64 << 8 | 64; + + public static ColorHighlight red(int slot) { + return new ColorHighlight(slot, RED_HIGHLIGHT); + } + + public static ColorHighlight yellow(int slot) { + return new ColorHighlight(slot, YELLOW_HIGHLIGHT); + } + + public static ColorHighlight green(int slot) { + return new ColorHighlight(slot, GREEN_HIGHLIGHT); + } + + public static ColorHighlight gray(int slot) { + return new ColorHighlight(slot, 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..c5e3cf09 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; @@ -10,23 +11,27 @@ 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 { - 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; + private final Pattern containerName; - public ContainerSolver(String containerName) { - CONTAINER_NAME = Pattern.compile(containerName); + protected ContainerSolver(String containerName) { + this.containerName = Pattern.compile(containerName); } - public abstract boolean isEnabled(); + protected abstract boolean isEnabled(); public Pattern getName() { - return CONTAINER_NAME; + return containerName; } - 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..0c27704d 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,17 +78,22 @@ 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 = null; + if (currentSolver != null) { + currentSolver.reset(); + currentSolver = null; + } } public void markDirty() { diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java index 2638db7e..aefe11c6 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java @@ -1,19 +1,32 @@ 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.inventory.SimpleInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; 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.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -29,28 +42,63 @@ public abstract class HandledScreenMixin extends Screen { @Inject(at = @At("HEAD"), method = "keyPressed") public void skyblocker$keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable<Boolean> cir) { - if (this.focusedSlot != null) { - if (keyCode != 256 && !this.client.options.inventoryKey.matchesKey(keyCode, scanCode)) { - if (WikiLookup.wikiLookup.matchesKey(keyCode, scanCode)) WikiLookup.openWiki(this.focusedSlot); - } + if (this.client != null && this.focusedSlot != null && keyCode != 256 && !this.client.options.inventoryKey.matchesKey(keyCode, scanCode) && WikiLookup.wikiLookup.matchesKey(keyCode, scanCode)) { + WikiLookup.openWiki(this.focusedSlot); } } @Inject(at = @At("HEAD"), method = "drawMouseoverTooltip", cancellable = true) public void skyblocker$drawMouseOverTooltip(DrawContext context, int x, int y, CallbackInfo ci) { - //Hide Empty Tooltips - if(this.focusedSlot != null) { - Text stackName = focusedSlot.getStack().getName(); - String strName = stackName.getString(); - if(Utils.isOnSkyblock() && SkyblockerConfig.get().general.hideEmptyTooltips && strName.equals(" ")) ci.cancel(); - } - - //Backpack Preview - String title = this.getTitle().getString(); + // Hide Empty Tooltips + if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.hideEmptyTooltips && this.focusedSlot != null && focusedSlot.getStack().getName().getString().equals(" ")) { + ci.cancel(); + } + + // Backpack Preview boolean shiftDown = SkyblockerConfig.get().general.backpackPreviewWithoutShift ^ Screen.hasShiftDown(); - if (shiftDown && title.equals("Storage") && this.focusedSlot != null) { - if (this.focusedSlot.inventory == this.client.player.getInventory()) return; - if (BackpackPreview.renderPreview(context, this.focusedSlot.getIndex(), x, y)) ci.cancel(); + if (this.client != null && this.client.player != null && this.focusedSlot != null && shiftDown && this.getTitle().getString().equals("Storage") && this.focusedSlot.inventory != this.client.player.getInventory() && BackpackPreview.renderPreview(context, this.focusedSlot.getIndex(), x, y)) { + ci.cancel(); + } + } + + @Redirect(method = "drawMouseoverTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/slot/Slot;getStack()Lnet/minecraft/item/ItemStack;", ordinal = 0)) + private ItemStack skyblocker$experimentSolvers$replaceTooltipDisplayStack(Slot slot) { + return skyblocker$experimentSolvers$getStack(slot); + } + + @ModifyVariable(method = "drawSlot", at = @At(value = "LOAD", ordinal = 4), ordinal = 0) + private ItemStack skyblocker$experimentSolvers$replaceDisplayStack(ItemStack stack, DrawContext context, Slot slot) { + return skyblocker$experimentSolvers$getStack(slot); + } + + @Unique + 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 skyblocker$experimentSolvers$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 (experimentSolver instanceof ChronomatronSolver chronomatronSolver) { + Item item = chronomatronSolver.getChronomatronSlots().get(chronomatronSolver.getChronomatronCurrentOrdinal()); + if ((slot.getStack().isOf(item) || ChronomatronSolver.TERRACOTTA_TO_GLASS.get(slot.getStack().getItem()) == item) && chronomatronSolver.incrementChronomatronCurrentOrdinal() >= chronomatronSolver.getChronomatronSlots().size()) { + chronomatronSolver.setState(ExperimentSolver.State.END); + } + } else if (experimentSolver instanceof SuperpairsSolver superpairsSolver) { + superpairsSolver.setSuperpairsPrevClickedSlot(slot.getIndex()); + superpairsSolver.setSuperpairsCurrentSlot(ItemStack.EMPTY); + } else if (experimentSolver instanceof UltrasequencerSolver ultrasequencerSolver && 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..2d868782 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/dungeon/CroesusHelper.java @@ -11,20 +11,23 @@ import java.util.Map; public class CroesusHelper extends ContainerSolver { - public CroesusHelper() { super("^Croesus$"); } + 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(); - if (stack != null && stack.getNbt() != null && stack.getNbt().toString().contains("opened")) - highlights.add(new ColorHighlight(entry.getKey(), GRAY_HIGHLIGHT)); + if (stack != null && stack.getNbt() != null && stack.getNbt().toString().contains("opened")) { + highlights.add(ColorHighlight.gray(entry.getKey())); + } } return highlights; } 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..add30907 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 @@ -6,7 +6,6 @@ import me.xmrvizzy.skyblocker.gui.ContainerSolver; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -// import net.minecraft.registry.Registry; import net.minecraft.registry.Registries; import net.minecraft.util.DyeColor; import net.minecraft.util.Identifier; @@ -27,27 +26,28 @@ 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]; - if(targetColor == null) { + if (targetColor == null) { targetColor = colorFromName.get(colorString); - if(targetColor == null) { + if (targetColor == null) { LOGGER.error("[Skyblocker] Couldn't find dye color corresponding to \"" + colorString + "\""); return Collections.emptyList(); } } - for(Map.Entry<Integer, ItemStack> slot : slots.entrySet()) { + for (Map.Entry<Integer, ItemStack> slot : slots.entrySet()) { ItemStack itemStack = slot.getValue(); - if(!itemStack.hasEnchantments() && targetColor.equals(itemColor.get(itemStack.getItem()))) - highlights.add(new ColorHighlight(slot.getKey(), GREEN_HIGHLIGHT)); + if (!itemStack.hasEnchantments() && targetColor.equals(itemColor.get(itemStack.getItem()))) { + highlights.add(ColorHighlight.green(slot.getKey())); + } } return highlights; } @@ -63,7 +63,6 @@ public class ColorTerminal extends ContainerSolver { itemColor = new HashMap<>(); for (DyeColor color : DyeColor.values()) for (String item : new String[]{"dye", "wool", "stained_glass", "terracotta"}) - // itemColor.put(Registry.ITEM.get(new Identifier(color.getName() + '_' + item)), color); itemColor.put(Registries.ITEM.get(new Identifier(color.getName() + '_' + item)), color); itemColor.put(Items.BONE_MEAL, DyeColor.WHITE); itemColor.put(Items.LAPIS_LAZULI, DyeColor.BLUE); 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..18326254 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,19 +15,20 @@ 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<>(); - for(Map.Entry<Integer, ItemStack> slot : slots.entrySet()) { + for (Map.Entry<Integer, ItemStack> slot : slots.entrySet()) { ItemStack stack = slot.getValue(); - if(!stack.hasEnchantments() && stack.getName().getString().startsWith(prefix)) - highlights.add(new ColorHighlight(slot.getKey(), GREEN_HIGHLIGHT)); + if (!stack.hasEnchantments() && stack.getName().getString().startsWith(prefix)) { + highlights.add(ColorHighlight.green(slot.getKey())); + } } return highlights; } 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..40793169 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/ChronomatronSolver.java @@ -0,0 +1,128 @@ +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 \\(\\w+\\)$"); + } + + 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 (getState()) { + 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())); + setState(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: ")) { + setState(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; + setState(State.REMEMBER); + } else { + reset(); + } + } + } + } + } else { + reset(); + } + } + + @Override + protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) { + List<ColorHighlight> highlights = new ArrayList<>(); + if (getState() == State.SHOW && chronomatronSlots.size() > chronomatronCurrentOrdinal) { + 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..5dad908e --- /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 + } + + private State state = State.REMEMBER; + private 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..9f6e8b2a --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/SuperpairsSolver.java @@ -0,0 +1,81 @@ +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.client.gui.screen.ingame.GenericContainerScreen; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; + +import java.util.*; + +public class SuperpairsSolver extends ExperimentSolver { + private int superpairsPrevClickedSlot; + private ItemStack superpairsCurrentSlot; + private final Set<Integer> superpairsDuplicatedSlots = new HashSet<>(); + + public SuperpairsSolver() { + super("^Superpairs \\(\\w+\\)$"); + } + + 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 start(GenericContainerScreen screen) { + super.start(screen); + setState(State.SHOW); + } + + @Override + protected void tick(Screen screen) { + if (isEnabled() && screen instanceof GenericContainerScreen genericContainerScreen && genericContainerScreen.getTitle().getString().startsWith("Superpairs (")) { + if (getState() == State.SHOW) { + if (genericContainerScreen.getScreenHandler().getInventory().getStack(4).isOf(Items.CAULDRON)) { + reset(); + } else if (getSlots().get(superpairsPrevClickedSlot) == null) { + ItemStack itemStack = genericContainerScreen.getScreenHandler().getInventory().getStack(superpairsPrevClickedSlot); + if (!(itemStack.isOf(Items.CYAN_STAINED_GLASS) || itemStack.isOf(Items.BLACK_STAINED_GLASS_PANE) || itemStack.isOf(Items.AIR))) { + getSlots().entrySet().stream().filter((entry -> ItemStack.areEqual(entry.getValue(), itemStack))).findAny().ifPresent(entry -> superpairsDuplicatedSlots.add(entry.getKey())); + getSlots().put(superpairsPrevClickedSlot, itemStack); + superpairsCurrentSlot = itemStack; + } + } + } + } else { + reset(); + } + } + + @Override + protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> displaySlots) { + List<ColorHighlight> highlights = new ArrayList<>(); + if (getState() == State.SHOW) { + for (Map.Entry<Integer, ItemStack> indexStack : displaySlots.entrySet()) { + int index = indexStack.getKey(); + ItemStack displayStack = indexStack.getValue(); + ItemStack stack = getSlots().get(index); + if (stack != null && !ItemStack.areEqual(stack, displayStack)) { + if (ItemStack.areEqual(superpairsCurrentSlot, stack) && displayStack.getName().getString().equals("Click a second button!")) { + highlights.add(ColorHighlight.green(index)); + } else if (superpairsDuplicatedSlots.contains(index)) { + highlights.add(ColorHighlight.yellow(index)); + } else { + highlights.add(ColorHighlight.red(index)); + } + } + } + } + return highlights; + } +} 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..45d6c0c6 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/experiment/UltrasequencerSolver.java @@ -0,0 +1,80 @@ +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.client.gui.screen.ingame.GenericContainerScreen; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class UltrasequencerSolver extends ExperimentSolver { + private int ultrasequencerNextSlot; + + public UltrasequencerSolver() { + super("^Ultrasequencer \\(\\w+\\)$"); + } + + 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) { + if (isEnabled() && screen instanceof GenericContainerScreen genericContainerScreen && genericContainerScreen.getTitle().getString().startsWith("Ultrasequencer (")) { + switch (getState()) { + case REMEMBER -> { + Inventory inventory = genericContainerScreen.getScreenHandler().getInventory(); + if (inventory.getStack(49).getName().getString().equals("Remember the pattern!")) { + for (int index = 9; index < 45; index++) { + ItemStack itemStack = inventory.getStack(index); + String name = itemStack.getName().getString(); + if (name.matches("\\d+")) { + if (name.equals("1")) { + ultrasequencerNextSlot = index; + } + getSlots().put(index, itemStack); + } + } + setState(State.WAIT); + } + } + case WAIT -> { + if (genericContainerScreen.getScreenHandler().getInventory().getStack(49).getName().getString().startsWith("Timer: ")) { + setState(State.SHOW); + } + } + case END -> { + String name = genericContainerScreen.getScreenHandler().getInventory().getStack(49).getName().getString(); + if (!name.startsWith("Timer: ")) { + if (name.equals("Remember the pattern!")) { + getSlots().clear(); + setState(State.REMEMBER); + } else { + reset(); + } + } + } + } + } else { + reset(); + } + } + + @Override + protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) { + return getState() == State.SHOW && ultrasequencerNextSlot != 0 ? List.of(ColorHighlight.green(ultrasequencerNextSlot)) : new ArrayList<>(); + } +} |