From 5cb4732d47aad82b5a9447ee4fcec2e36ff465e5 Mon Sep 17 00:00:00 2001 From: Rime <81419447+Emirlol@users.noreply.github.com> Date: Tue, 13 Aug 2024 11:04:23 +0300 Subject: Clean up some stuff and fix SuperpairsSolver not starting properly --- .../java/de/hysky/skyblocker/SkyblockerMod.java | 3 +- .../mixins/GenericContainerScreenHandlerMixin.java | 6 +- .../skyblocker/mixins/HandledScreenMixin.java | 48 ++--- .../skyblock/experiment/ChronomatronSolver.java | 202 ++++++++++----------- .../skyblock/experiment/ExperimentSolver.java | 8 +- .../skyblock/experiment/SuperpairsSolver.java | 139 +++++++------- .../skyblock/experiment/UltrasequencerSolver.java | 128 ++++++------- .../utils/container/ContainerSolver.java | 9 +- .../utils/container/ContainerSolverManager.java | 87 ++++----- 9 files changed, 298 insertions(+), 332 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index 405827e0..4d302ac5 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -87,7 +87,6 @@ public class SkyblockerMod implements ClientModInitializer { public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); public static final Gson GSON_COMPACT = new GsonBuilder().create(); private static SkyblockerMod INSTANCE; - public final ContainerSolverManager containerSolverManager = new ContainerSolverManager(); public final StatusBarTracker statusBarTracker = new StatusBarTracker(); /** @@ -202,7 +201,7 @@ public class SkyblockerMod implements ClientModInitializer { FancyStatusBars.init(); SkyblockInventoryScreen.initEquipment(); EventNotifications.init(); - containerSolverManager.init(); + ContainerSolverManager.init(); statusBarTracker.init(); BeaconHighlighter.init(); WarpAutocomplete.init(); diff --git a/src/main/java/de/hysky/skyblocker/mixins/GenericContainerScreenHandlerMixin.java b/src/main/java/de/hysky/skyblocker/mixins/GenericContainerScreenHandlerMixin.java index 3c3dbd52..a487dbf9 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/GenericContainerScreenHandlerMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/GenericContainerScreenHandlerMixin.java @@ -1,9 +1,9 @@ package de.hysky.skyblocker.mixins; -import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.dungeon.partyfinder.PartyFinderScreen; import de.hysky.skyblocker.skyblock.item.SkyblockInventoryScreen; import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.container.ContainerSolverManager; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; @@ -25,7 +25,7 @@ public abstract class GenericContainerScreenHandlerMixin extends ScreenHandler { @Override public void setStackInSlot(int slot, int revision, ItemStack stack) { super.setStackInSlot(slot, revision, stack); - SkyblockerMod.getInstance().containerSolverManager.markDirty(); + ContainerSolverManager.markHighlightsDirty(); Screen currentScreen = MinecraftClient.getInstance().currentScreen; switch (currentScreen) { @@ -47,7 +47,7 @@ public abstract class GenericContainerScreenHandlerMixin extends ScreenHandler { @Override public void updateSlotStacks(int revision, List stacks, ItemStack cursorStack) { super.updateSlotStacks(revision, stacks, cursorStack); - SkyblockerMod.getInstance().containerSolverManager.markDirty(); + ContainerSolverManager.markHighlightsDirty(); if (MinecraftClient.getInstance().currentScreen instanceof PartyFinderScreen screen) { screen.markDirty(); } diff --git a/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java index 2ef599dd..01147120 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java @@ -7,7 +7,6 @@ import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.PetCache; import de.hysky.skyblocker.skyblock.bazaar.BazaarHelper; -import de.hysky.skyblocker.skyblock.experiment.ChronomatronSolver; import de.hysky.skyblocker.skyblock.experiment.ExperimentSolver; import de.hysky.skyblocker.skyblock.experiment.SuperpairsSolver; import de.hysky.skyblocker.skyblock.experiment.UltrasequencerSolver; @@ -24,11 +23,11 @@ import de.hysky.skyblocker.skyblock.quicknav.QuickNavButton; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.container.ContainerSolver; +import de.hysky.skyblocker.utils.container.ContainerSolverManager; 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.GenericContainerScreenHandler; import net.minecraft.screen.ScreenHandler; @@ -50,7 +49,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.regex.Matcher; @@ -208,11 +206,19 @@ public abstract class HandledScreenMixin extends Screen } /** - * Redirects getStack calls to account for different stacks in experiment solvers. + * Avoids getting currentSolver again when it's already in the scope for some usages of this method. + * @see #skyblocker$experimentSolvers$getStack(Slot, ItemStack, ContainerSolver) */ @Unique private ItemStack skyblocker$experimentSolvers$getStack(Slot slot, @NotNull ItemStack stack) { - ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver(); + return skyblocker$experimentSolvers$getStack(slot, stack, ContainerSolverManager.getCurrentSolver()); + } + + /** + * Redirects getStack calls to account for different stacks in experiment solvers. + */ + @Unique + private ItemStack skyblocker$experimentSolvers$getStack(Slot slot, @NotNull ItemStack stack, ContainerSolver currentSolver) { 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 ? stack : itemStack; @@ -239,13 +245,13 @@ public abstract class HandledScreenMixin extends Screen if (slot == null) return; String title = getTitle().getString(); - ItemStack stack = skyblocker$experimentSolvers$getStack(slot, slot.getStack()); - ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver(); + ContainerSolver currentSolver = ContainerSolverManager.getCurrentSolver(); + ItemStack stack = skyblocker$experimentSolvers$getStack(slot, slot.getStack(), currentSolver); // Prevent clicks on filler items if (SkyblockerConfigManager.get().uiAndVisuals.hideEmptyTooltips && FILLER_ITEMS.contains(stack.getName().getString()) && // Allow clicks in Ultrasequencer and Superpairs - (!UltrasequencerSolver.INSTANCE.getTitlePattern().matcher(title).matches() || SkyblockerConfigManager.get().helpers.experiments.enableUltrasequencerSolver)) { + (!UltrasequencerSolver.INSTANCE.test(title) || SkyblockerConfigManager.get().helpers.experiments.enableUltrasequencerSolver)) { ci.cancel(); return; } @@ -300,34 +306,10 @@ public abstract class HandledScreenMixin extends Screen } if (currentSolver != null) { - boolean disallowed = SkyblockerMod.getInstance().containerSolverManager.onSlotClick(slotId, stack); + boolean disallowed = ContainerSolverManager.onSlotClick(slotId, stack); if (disallowed) ci.cancel(); } - - // Experiment Solvers - if (currentSolver instanceof ExperimentSolver experimentSolver && experimentSolver.getState() == ExperimentSolver.State.SHOW && slot.inventory instanceof SimpleInventory) { - switch (experimentSolver) { - case ChronomatronSolver chronomatronSolver -> { - Item item = chronomatronSolver.getChronomatronSlots().get(chronomatronSolver.getChronomatronCurrentOrdinal()); - if ((stack.isOf(item) || ChronomatronSolver.TERRACOTTA_TO_GLASS.get(stack.getItem()) == item) && chronomatronSolver.incrementChronomatronCurrentOrdinal() >= chronomatronSolver.getChronomatronSlots().size()) { - chronomatronSolver.setState(ExperimentSolver.State.END); - } - } - - case SuperpairsSolver superpairsSolver -> { - superpairsSolver.setSuperpairsPrevClickedSlot(slot.getIndex()); - superpairsSolver.setSuperpairsCurrentSlot(ItemStack.EMPTY); - } - - case UltrasequencerSolver ultrasequencerSolver when slot.getIndex() == ultrasequencerSolver.getUltrasequencerNextSlot() -> { - int count = ultrasequencerSolver.getSlots().get(ultrasequencerSolver.getUltrasequencerNextSlot()).getCount() + 1; - ultrasequencerSolver.getSlots().entrySet().stream().filter(entry -> entry.getValue().getCount() == count).findAny().map(Map.Entry::getKey).ifPresentOrElse(ultrasequencerSolver::setUltrasequencerNextSlot, () -> ultrasequencerSolver.setState(ExperimentSolver.State.END)); - } - - default -> { /*Do Nothing*/ } - } - } } @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V")) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/experiment/ChronomatronSolver.java b/src/main/java/de/hysky/skyblocker/skyblock/experiment/ChronomatronSolver.java index a4d34a1b..fe63b0a6 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/experiment/ChronomatronSolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/experiment/ChronomatronSolver.java @@ -1,128 +1,120 @@ package de.hysky.skyblocker.skyblock.experiment; -import com.google.common.collect.ImmutableMap; - import de.hysky.skyblocker.config.configs.HelperConfig; import de.hysky.skyblocker.utils.render.gui.ColorHighlight; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import net.minecraft.client.gui.screen.Screen; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; 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; public final class ChronomatronSolver extends ExperimentSolver { - public static final ImmutableMap 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 chronomatronSlots = new ArrayList<>(); - private int chronomatronChainLengthCount; - private int chronomatronCurrentSlot; - private int chronomatronCurrentOrdinal; - - public ChronomatronSolver() { - super("^Chronomatron \\(\\w+\\)$"); - } + public static final Object2ObjectMap TERRACOTTA_TO_GLASS = Object2ObjectMaps.unmodifiable( + new Object2ObjectArrayMap<>( + new Item[]{ + Items.RED_TERRACOTTA, Items.ORANGE_TERRACOTTA, Items.YELLOW_TERRACOTTA, Items.LIME_TERRACOTTA, Items.GREEN_TERRACOTTA, Items.CYAN_TERRACOTTA, Items.LIGHT_BLUE_TERRACOTTA, Items.BLUE_TERRACOTTA, Items.PURPLE_TERRACOTTA, Items.PINK_TERRACOTTA + }, + new Item[]{ + Items.RED_STAINED_GLASS, Items.ORANGE_STAINED_GLASS, Items.YELLOW_STAINED_GLASS, Items.LIME_STAINED_GLASS, Items.GREEN_STAINED_GLASS, Items.CYAN_STAINED_GLASS, Items.LIGHT_BLUE_STAINED_GLASS, Items.BLUE_STAINED_GLASS, Items.PURPLE_STAINED_GLASS, Items.PINK_STAINED_GLASS + } + ) + ); - public List getChronomatronSlots() { - return chronomatronSlots; - } + private final List chronomatronSlots = new ArrayList<>(); + private int chronomatronChainLengthCount; + private int chronomatronCurrentSlot; + private int chronomatronCurrentOrdinal; - public int getChronomatronCurrentOrdinal() { - return chronomatronCurrentOrdinal; - } + public ChronomatronSolver() { + super("^Chronomatron \\(\\w+\\)$"); + } - public int incrementChronomatronCurrentOrdinal() { - return ++chronomatronCurrentOrdinal; - } + @Override + public boolean onClickSlot(int slot, ItemStack stack, int screenId) { + if (getState() == State.SHOW) { + Item item = chronomatronSlots.get(chronomatronCurrentOrdinal); + if ((stack.isOf(item) || ChronomatronSolver.TERRACOTTA_TO_GLASS.get(stack.getItem()) == item) && ++chronomatronCurrentOrdinal >= chronomatronSlots.size()) { + setState(ExperimentSolver.State.END); + } + } + return super.onClickSlot(slot, stack, screenId); + } - @Override - protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { - return experimentsConfig.enableChronomatronSolver; - } + @Override + protected boolean isEnabled(HelperConfig.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).hasGlint()) { - 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).hasGlint()) { - 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 void tick(GenericContainerScreen screen) { + switch (getState()) { + case REMEMBER -> { + Inventory inventory = screen.getScreenHandler().getInventory(); + if (chronomatronCurrentSlot == 0) { + for (int index = 10; index < 43; index++) { + if (inventory.getStack(index).hasGlint()) { + 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).hasGlint()) { + chronomatronCurrentSlot = 0; + } + } + case WAIT -> { + if (screen.getScreenHandler().getInventory().getStack(49).getName().getString().startsWith("Timer: ")) { + setState(State.SHOW); + } + } + case END -> { + String name = screen.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(); + } + } + } + } + } - @Override - public List getColors(Int2ObjectMap slots) { - List highlights = new ArrayList<>(); - if (getState() == State.SHOW && chronomatronSlots.size() > chronomatronCurrentOrdinal) { - for (Int2ObjectMap.Entry indexStack : slots.int2ObjectEntrySet()) { - int index = indexStack.getIntKey(); - 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 + public List getColors(Int2ObjectMap slots) { + List highlights = new ArrayList<>(); + if (getState() == State.SHOW && chronomatronSlots.size() > chronomatronCurrentOrdinal) { + for (Int2ObjectMap.Entry indexStack : slots.int2ObjectEntrySet()) { + int index = indexStack.getIntKey(); + 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 - public void reset() { - chronomatronSlots.clear(); - chronomatronChainLengthCount = 0; - chronomatronCurrentSlot = 0; - chronomatronCurrentOrdinal = 0; - } + @Override + public void reset() { + chronomatronSlots.clear(); + chronomatronChainLengthCount = 0; + chronomatronCurrentSlot = 0; + chronomatronCurrentOrdinal = 0; + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/experiment/ExperimentSolver.java b/src/main/java/de/hysky/skyblocker/skyblock/experiment/ExperimentSolver.java index 808dce2e..931052b5 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/experiment/ExperimentSolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/experiment/ExperimentSolver.java @@ -3,10 +3,9 @@ package de.hysky.skyblocker.skyblock.experiment; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.config.configs.HelperConfig; import de.hysky.skyblocker.utils.container.SimpleContainerSolver; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; 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 org.intellij.lang.annotations.Language; @@ -46,7 +45,8 @@ public abstract sealed class ExperimentSolver extends SimpleContainerSolver perm @Override public void start(GenericContainerScreen screen) { state = State.REMEMBER; - ScreenEvents.afterTick(screen).register(this::tick); + //No reason to use the screen lambda argument given by `register` as it narrows down the type of our screen for no reason + ScreenEvents.afterTick(screen).register(ignored -> tick(screen)); } @Override @@ -55,5 +55,5 @@ public abstract sealed class ExperimentSolver extends SimpleContainerSolver perm slots.clear(); } - protected abstract void tick(Screen screen); + protected abstract void tick(GenericContainerScreen screen); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/experiment/SuperpairsSolver.java b/src/main/java/de/hysky/skyblocker/skyblock/experiment/SuperpairsSolver.java index 7dc76b1d..6d77a67b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/experiment/SuperpairsSolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/experiment/SuperpairsSolver.java @@ -3,84 +3,89 @@ package de.hysky.skyblocker.skyblock.experiment; import de.hysky.skyblocker.config.configs.HelperConfig; import de.hysky.skyblocker.utils.render.gui.ColorHighlight; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; -import net.minecraft.client.gui.screen.Screen; +import it.unimi.dsi.fastutil.ints.IntIntImmutablePair; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import java.util.*; +import java.util.ArrayList; +import java.util.List; public final class SuperpairsSolver extends ExperimentSolver { - private int superpairsPrevClickedSlot; - private ItemStack superpairsCurrentSlot; - private final IntSet superpairsDuplicatedSlots = new IntOpenHashSet(); + private int superpairsPrevClickedSlot = 0; + private ItemStack superpairsCurrentSlot = ItemStack.EMPTY; + private final List superpairsDuplicatedSlots = new ObjectArrayList<>(14); - public SuperpairsSolver() { - super("^Superpairs \\(\\w+\\)$"); - } + @Override + public boolean onClickSlot(int slot, ItemStack stack, int screenId) { + if (getState() == State.SHOW) { + this.superpairsPrevClickedSlot = slot; + this.superpairsCurrentSlot = ItemStack.EMPTY; + } + return super.onClickSlot(slot, stack, screenId); + } - public void setSuperpairsPrevClickedSlot(int superpairsPrevClickedSlot) { - this.superpairsPrevClickedSlot = superpairsPrevClickedSlot; - } + public SuperpairsSolver() { + super("^Superpairs \\(\\w+\\)$"); + } - public void setSuperpairsCurrentSlot(ItemStack superpairsCurrentSlot) { - this.superpairsCurrentSlot = superpairsCurrentSlot; - } + @Override + protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { + return experimentsConfig.enableSuperpairsSolver; + } - @Override - protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { - return experimentsConfig.enableSuperpairsSolver; - } + @Override + public void start(GenericContainerScreen screen) { + super.start(screen); + setState(State.SHOW); + } - @Override - public void start(GenericContainerScreen screen) { - setState(State.SHOW); - } + @Override + public void reset() { + superpairsPrevClickedSlot = 0; + superpairsCurrentSlot = ItemStack.EMPTY; + superpairsDuplicatedSlots.clear(); + } - @Override - public void reset() { - superpairsPrevClickedSlot = 0; - superpairsCurrentSlot = null; - superpairsDuplicatedSlots.clear(); - } + @Override + protected void tick(GenericContainerScreen screen) { + if (getState() == State.SHOW && getSlots().get(superpairsPrevClickedSlot) == null) { + ItemStack itemStack = screen.getScreenHandler().getInventory().getStack(superpairsPrevClickedSlot); + if (!(itemStack.isOf(Items.CYAN_STAINED_GLASS) || itemStack.isOf(Items.BLACK_STAINED_GLASS_PANE) || itemStack.isOf(Items.AIR))) { + getSlots().int2ObjectEntrySet().stream() + .filter(entry -> ItemStack.areEqual(entry.getValue(), itemStack)) + .findAny() + .ifPresent(entry -> superpairsDuplicatedSlots.add(IntIntImmutablePair.of(entry.getIntKey(), superpairsPrevClickedSlot))); + getSlots().put(superpairsPrevClickedSlot, itemStack); + superpairsCurrentSlot = itemStack; + } + } + } - @Override - protected void tick(Screen screen) { - if (isEnabled() && screen instanceof GenericContainerScreen genericContainerScreen && genericContainerScreen.getTitle().getString().startsWith("Superpairs (")) { - if (getState() == State.SHOW && 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().int2ObjectEntrySet().stream().filter((entry -> ItemStack.areEqual(entry.getValue(), itemStack))).findAny().ifPresent(entry -> superpairsDuplicatedSlots.add(entry.getIntKey())); - getSlots().put(superpairsPrevClickedSlot, itemStack); - superpairsCurrentSlot = itemStack; - } - } - } else { - reset(); - } - } - - @Override - public List getColors(Int2ObjectMap displaySlots) { - List highlights = new ArrayList<>(); - if (getState() == State.SHOW) { - for (Int2ObjectMap.Entry indexStack : displaySlots.int2ObjectEntrySet()) { - int index = indexStack.getIntKey(); - 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; - } + @Override + public List getColors(Int2ObjectMap displaySlots) { + List highlights = new ArrayList<>(); + if (getState() == State.SHOW) { + for (Int2ObjectMap.Entry indexStack : displaySlots.int2ObjectEntrySet()) { + int index = indexStack.getIntKey(); + 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 { + superpairsDuplicatedSlots.stream() + .filter(entry -> entry.leftInt() == index || entry.rightInt() == index) + .findFirst() + .ifPresentOrElse(pair -> { + highlights.add(ColorHighlight.green(pair.leftInt())); + highlights.add(ColorHighlight.green(pair.rightInt())); + }, () -> highlights.add(ColorHighlight.red(index))); + } + } + } + } + return highlights; + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java b/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java index f39c1ffe..9d0df2a9 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java @@ -1,10 +1,9 @@ package de.hysky.skyblocker.skyblock.experiment; import de.hysky.skyblocker.config.configs.HelperConfig; +import de.hysky.skyblocker.utils.container.ContainerSolverManager; import de.hysky.skyblocker.utils.render.gui.ColorHighlight; -import de.hysky.skyblocker.utils.container.ContainerSolver; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -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; @@ -13,71 +12,72 @@ import java.util.ArrayList; import java.util.List; public final class UltrasequencerSolver extends ExperimentSolver { - public static final UltrasequencerSolver INSTANCE = new UltrasequencerSolver(); - private int ultrasequencerNextSlot; + public static final UltrasequencerSolver INSTANCE = new UltrasequencerSolver(); + private int ultrasequencerNextSlot; - private UltrasequencerSolver() { - super("^Ultrasequencer \\(\\w+\\)$"); - } + @Override + public boolean onClickSlot(int slot, ItemStack stack, int screenId) { + if (getState() == State.SHOW && slot == ultrasequencerNextSlot) { + int count = getSlots().get(ultrasequencerNextSlot).getCount() + 1; + getSlots().int2ObjectEntrySet().stream() + .filter(entry -> entry.getValue().getCount() == count) + .findAny() + .map(Int2ObjectMap.Entry::getIntKey) + .ifPresentOrElse(nextSlot -> this.ultrasequencerNextSlot = nextSlot, () -> setState(ExperimentSolver.State.END)); + } + return super.onClickSlot(slot, stack, screenId); + } - public int getUltrasequencerNextSlot() { - return ultrasequencerNextSlot; - } + private UltrasequencerSolver() { + super("^Ultrasequencer \\(\\w+\\)$"); + } - public void setUltrasequencerNextSlot(int ultrasequencerNextSlot) { - this.ultrasequencerNextSlot = ultrasequencerNextSlot; - } + @Override + protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { + return experimentsConfig.enableUltrasequencerSolver; + } - @Override - protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { - return experimentsConfig.enableUltrasequencerSolver; - } + @Override + protected void tick(GenericContainerScreen screen) { + switch (getState()) { + case REMEMBER -> { + Inventory inventory = screen.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 (screen.getScreenHandler().getInventory().getStack(49).getName().getString().startsWith("Timer: ")) { + setState(State.SHOW); + ContainerSolverManager.markHighlightsDirty(); + } + } + case END -> { + String name = screen.getScreenHandler().getInventory().getStack(49).getName().getString(); + if (!name.startsWith("Timer: ")) { + if (name.equals("Remember the pattern!")) { + getSlots().clear(); + setState(State.REMEMBER); + } else { + reset(); + } + } + } + } + } - @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); - ContainerSolver.markHighlightsDirty(); - } - } - 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 - public List getColors(Int2ObjectMap slots) { - return getState() == State.SHOW && ultrasequencerNextSlot != 0 ? List.of(ColorHighlight.green(ultrasequencerNextSlot)) : new ArrayList<>(); - } + @Override + public List getColors(Int2ObjectMap slots) { + return getState() == State.SHOW && ultrasequencerNextSlot != 0 ? List.of(ColorHighlight.green(ultrasequencerNextSlot)) : new ArrayList<>(); + } } diff --git a/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolver.java b/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolver.java index c6162049..ece56863 100644 --- a/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolver.java +++ b/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolver.java @@ -1,6 +1,5 @@ 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; @@ -17,14 +16,14 @@ public interface ContainerSolver extends ContainerMatcher, Resettable { @Override default void reset() {} + /** + * Called when the slot is clicked. + * @return {@code true} if the click should be canceled, {@code false} otherwise. Defaults to {@code false} if not overridden. + */ default boolean onClickSlot(int slot, ItemStack stack, int screenId) { return false; } - static void markHighlightsDirty() { - SkyblockerMod.getInstance().containerSolverManager.markDirty(); - } - static void trimEdges(Int2ObjectMap slots, int rows) { for (int i = 0; i < rows; i++) { slots.remove(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 index cf98941c..11c8491a 100644 --- a/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolverManager.java +++ b/src/main/java/de/hysky/skyblocker/utils/container/ContainerSolverManager.java @@ -34,38 +34,36 @@ 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 highlights; + private static final ContainerSolver[] 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, + ChocolateFactorySolver.INSTANCE, + new ReorderHelper() + }; + private static ContainerSolver currentSolver = null; + private static List 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; + private static 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, - ChocolateFactorySolver.INSTANCE, - new ReorderHelper() - }; - } + private ContainerSolverManager() {} - public ContainerSolver getCurrentSolver() { + public static ContainerSolver getCurrentSolver() { return currentSolver; } - public void init() { + public static 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) -> { @@ -83,23 +81,20 @@ public class ContainerSolverManager { }); } - public void onSetScreen(@NotNull GenericContainerScreen screen) { + @SuppressWarnings({"ConstantValue", "java:S1066"}) + public static 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)) { + //Ignore the result of instanceof being always true. + //This only happens because all solvers in the `solvers` array are SimpleContainerSolvers, which extend RegexContainerMatcher. + //This may not be the case as more and more solvers are added. + //Also don't merge this with the above `if`, the parenthesis mess gets hard to read. (java:S1066 for sonarlint users) + if ((solver instanceof RegexContainerMatcher containerMatcher && containerMatcher.test(screenName)) || solver.test(screen)) { ++screenId; currentSolver = solver; currentSolver.start(screen); - markDirty(); - + markHighlightsDirty(); return; } } @@ -107,33 +102,27 @@ public class ContainerSolverManager { clearScreen(); } - public void clearScreen() { + public static void clearScreen() { if (currentSolver != null) { currentSolver.reset(); currentSolver = null; } } - public void markDirty() { + public static void markHighlightsDirty() { 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 static boolean onSlotClick(int slot, ItemStack stack) { + return currentSolver != null && currentSolver.onClickSlot(slot, stack, screenId); } - public void onDraw(DrawContext context, List slots) { - if (currentSolver == null) - return; - if (highlights == null) - highlights = currentSolver.getColors(slotMap(slots)); + public static void onDraw(DrawContext context, List 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) { @@ -144,7 +133,7 @@ public class ContainerSolverManager { RenderSystem.colorMask(true, true, true, true); } - private Int2ObjectMap slotMap(List slots) { + private static Int2ObjectMap slotMap(List slots) { Int2ObjectMap slotMap = new Int2ObjectRBTreeMap<>(); for (int i = 0; i < slots.size(); i++) { slotMap.put(i, slots.get(i).getStack()); -- cgit