diff options
| author | Aaron <51387595+AzureAaron@users.noreply.github.com> | 2024-08-14 01:39:08 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-14 01:39:08 -0400 |
| commit | 931898c0846fba67e231c7318438338d42c0268f (patch) | |
| tree | 8828d387aa88ebc341ddf15627817242e1cf3bc4 /src/main/java | |
| parent | ac08fb6514defbac92876dc70e1ba98f7504ae24 (diff) | |
| parent | 57f8844f1404076dcd950c3e8473cf7746d3a8fc (diff) | |
| download | Skyblocker-931898c0846fba67e231c7318438338d42c0268f.tar.gz Skyblocker-931898c0846fba67e231c7318438338d42c0268f.tar.bz2 Skyblocker-931898c0846fba67e231c7318438338d42c0268f.zip | |
Merge pull request #918 from Emirlol/experiments-fix
Fix SuperpairsSolver not starting properly
Diffstat (limited to 'src/main/java')
9 files changed, 380 insertions, 336 deletions
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<ItemStack> 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<T extends ScreenHandler> 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<T extends ScreenHandler> 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<T extends ScreenHandler> 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..14bd3278 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,144 @@ 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<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 static final Object2ObjectMap<Item, Item> 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<Item> getChronomatronSlots() { - return chronomatronSlots; - } + /** + * The list of items to remember, in order. + */ + private final List<Item> chronomatronSlots = new ArrayList<>(); + /** + * The index of the current item shown in the chain, used for remembering. + */ + private int chronomatronChainLengthCount; + /** + * The slot id of the current item shown, used for detecting when the experiment finishes showing the current item. + */ + private int chronomatronCurrentSlot; + /** + * The next index in the chain to click. + */ + private int chronomatronCurrentOrdinal; - public int getChronomatronCurrentOrdinal() { - return chronomatronCurrentOrdinal; - } + public ChronomatronSolver() { + super("^Chronomatron \\(\\w+\\)$"); + } - public int incrementChronomatronCurrentOrdinal() { - return ++chronomatronCurrentOrdinal; - } + @Override + protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { + return experimentsConfig.enableChronomatronSolver; + } - @Override - protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { - return experimentsConfig.enableChronomatronSolver; - } + @Override + protected void tick(GenericContainerScreen screen) { + switch (getState()) { + case REMEMBER -> { + Inventory inventory = screen.getScreenHandler().getInventory(); + // Only try to look for items with enchantment glint if there is no item being currently shown. + if (chronomatronCurrentSlot == 0) { + for (int index = 10; index < 43; index++) { + if (inventory.getStack(index).hasGlint()) { + // If the list of items is smaller than the index of the current item shown, add the item to the list and set the state to wait. + if (chronomatronSlots.size() <= chronomatronChainLengthCount) { + chronomatronSlots.add(TERRACOTTA_TO_GLASS.get(inventory.getStack(index).getItem())); + setState(State.WAIT); + } else { + // If the item is already in the list, increment the current item shown index. + chronomatronChainLengthCount++; + } + // Remember the slot shown to detect when the experiment finishes showing the current item. + chronomatronCurrentSlot = index; + return; + } + } + // If the current item shown no longer has enchantment glint, the experiment finished showing the current item. + } 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: ")) { + // Get ready for another round if the instructions say to remember the pattern. + if (name.equals("Remember the pattern!")) { + chronomatronChainLengthCount = 0; + chronomatronCurrentOrdinal = 0; + setState(State.REMEMBER); + } else { + reset(); + } + } + } + } + } - @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(); - } - } + /** + * Highlights the slots that contain the item at index {@link #chronomatronCurrentOrdinal} of {@link #chronomatronSlots} in the chain. + */ + @Override + public List<ColorHighlight> getColors(Int2ObjectMap<ItemStack> slots) { + List<ColorHighlight> highlights = new ArrayList<>(); + if (getState() == State.SHOW && chronomatronSlots.size() > chronomatronCurrentOrdinal) { + for (Int2ObjectMap.Entry<ItemStack> 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<ColorHighlight> getColors(Int2ObjectMap<ItemStack> slots) { - List<ColorHighlight> highlights = new ArrayList<>(); - if (getState() == State.SHOW && chronomatronSlots.size() > chronomatronCurrentOrdinal) { - for (Int2ObjectMap.Entry<ItemStack> 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; - } + /** + * Increments {@link #chronomatronCurrentOrdinal} if the item clicked matches the item at {@link #chronomatronCurrentOrdinal the current index} in the chain. + */ + @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 - 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..9172f550 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/experiment/ExperimentSolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/experiment/ExperimentSolver.java @@ -3,20 +3,18 @@ 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; import org.jetbrains.annotations.NotNull; +/** + * The general class for all experiment solvers, implemented with a state machine. + */ public abstract sealed class ExperimentSolver extends SimpleContainerSolver permits ChronomatronSolver, SuperpairsSolver, UltrasequencerSolver { - public enum State { - REMEMBER, WAIT, SHOW, END - } - private State state = State.REMEMBER; private final Int2ObjectMap<ItemStack> slots = new Int2ObjectOpenHashMap<>(); @@ -46,7 +44,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 +54,24 @@ public abstract sealed class ExperimentSolver extends SimpleContainerSolver perm slots.clear(); } - protected abstract void tick(Screen screen); + protected abstract void tick(GenericContainerScreen screen); + + public enum State { + /** + * The state where the player has to remember the pattern. + */ + REMEMBER, + /** + * The state where the solver has remembered the pattern and is waiting for the show state. + */ + WAIT, + /** + * The state where the player has to recall the pattern and where the solver shows the player the pattern. + */ + SHOW, + /** + * The state where the player has finished recalling the pattern and the current round is over. + */ + END + } } 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..31909564 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,112 @@ 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.IntArraySet; import it.unimi.dsi.fastutil.ints.IntSet; -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.*; +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(); + /** + * The slot id of the last clicked slot. + */ + private int superpairsPrevClickedSlot = 0; + /** + * The item stack of the last clicked slot. + */ + private ItemStack superpairsCurrentSlot = ItemStack.EMPTY; + /** + * The set of slot ids that contain duplicated items. + */ + private final IntSet superpairsDuplicatedSlots = new IntArraySet(28); - public SuperpairsSolver() { - super("^Superpairs \\(\\w+\\)$"); - } + public SuperpairsSolver() { + super("^Superpairs \\(\\w+\\)$"); + } - public void setSuperpairsPrevClickedSlot(int superpairsPrevClickedSlot) { - this.superpairsPrevClickedSlot = superpairsPrevClickedSlot; - } + @Override + protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { + return experimentsConfig.enableSuperpairsSolver; + } - public void setSuperpairsCurrentSlot(ItemStack superpairsCurrentSlot) { - this.superpairsCurrentSlot = superpairsCurrentSlot; - } + /** + * Sets the state to {@link State#SHOW} since Superpairs does not require a state machine. + * @param screen + */ + @Override + public void start(GenericContainerScreen screen) { + super.start(screen); + setState(State.SHOW); + } - @Override - protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { - return experimentsConfig.enableSuperpairsSolver; - } + /** + * Checks the screen if the item of the last clicked slot is unknown. + * Adds duplicated items to the item of the last clicked slot to {@link #superpairsDuplicatedSlots}, + * save the item of the last clicked slot to the slot map, + * and sets {@link #superpairsCurrentSlot} to the item of the last clicked slot. + */ + @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(entry.getIntKey()); + superpairsDuplicatedSlots.add(superpairsPrevClickedSlot); + }); + getSlots().put(superpairsPrevClickedSlot, itemStack); + superpairsCurrentSlot = itemStack; + } + } + } - @Override - public void start(GenericContainerScreen screen) { - setState(State.SHOW); - } + /** + * Displays a green highlight on the slot that matches {@link #superpairsCurrentSlot} and the experiment is waiting for a second click. + * Displays a yellow highlight on the slots that contain duplicated items. + * Displays a red highlight on the slots that do not match anything. + */ + @Override + public List<ColorHighlight> getColors(Int2ObjectMap<ItemStack> displaySlots) { + List<ColorHighlight> highlights = new ArrayList<>(); + if (getState() == State.SHOW) { + for (Int2ObjectMap.Entry<ItemStack> 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 void reset() { - superpairsPrevClickedSlot = 0; - superpairsCurrentSlot = null; - superpairsDuplicatedSlots.clear(); - } + @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); + } - @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<ColorHighlight> getColors(Int2ObjectMap<ItemStack> displaySlots) { - List<ColorHighlight> highlights = new ArrayList<>(); - if (getState() == State.SHOW) { - for (Int2ObjectMap.Entry<ItemStack> 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 void reset() { + superpairsPrevClickedSlot = 0; + superpairsCurrentSlot = ItemStack.EMPTY; + superpairsDuplicatedSlots.clear(); + } } 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..1b731565 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java @@ -1,83 +1,96 @@ 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; -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(); + /** + * The slot id of the next slot to click. + */ + private int ultrasequencerNextSlot; - private UltrasequencerSolver() { - super("^Ultrasequencer \\(\\w+\\)$"); - } + private UltrasequencerSolver() { + super("^Ultrasequencer \\(\\w+\\)$"); + } - public int getUltrasequencerNextSlot() { - return ultrasequencerNextSlot; - } + @Override + protected boolean isEnabled(HelperConfig.Experiments experimentsConfig) { + return experimentsConfig.enableUltrasequencerSolver; + } - public void setUltrasequencerNextSlot(int ultrasequencerNextSlot) { - this.ultrasequencerNextSlot = ultrasequencerNextSlot; - } + /** + * Saves the shown items to {@link #slots the slot map}. + */ + @SuppressWarnings("JavadocReference") + @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(); + // Remember the item if its name is a number + if (name.matches("\\d+")) { + // Set the next slot to click to the item with the name "1" + if (name.equals("1")) { + ultrasequencerNextSlot = index; + } + // Save the item to the slot map + getSlots().put(index, |
