aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/de/hysky/skyblocker/SkyblockerMod.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java184
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java3
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java32
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java2
5 files changed, 115 insertions, 108 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
index dca41bd1..36ef5a4f 100644
--- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
+++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
@@ -18,6 +18,7 @@ import de.hysky.skyblocker.skyblock.dwarven.CrystalsLocationsManager;
import de.hysky.skyblocker.skyblock.dwarven.DwarvenHud;
import de.hysky.skyblocker.skyblock.end.BeaconHighlighter;
import de.hysky.skyblocker.skyblock.end.TheEnd;
+import de.hysky.skyblocker.skyblock.garden.VisitorHelper;
import de.hysky.skyblocker.skyblock.item.*;
import de.hysky.skyblocker.skyblock.item.tooltip.BackpackPreview;
import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip;
@@ -139,6 +140,7 @@ public class SkyblockerMod implements ClientModInitializer {
ItemProtection.init();
CreeperBeams.init();
Boulder.init();
+ VisitorHelper.init();
ItemRarityBackgrounds.init();
MuseumItemCache.init();
SecretsTracker.init();
diff --git a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java
index 9aeeb741..7d2f849e 100644
--- a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java
+++ b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java
@@ -17,11 +17,9 @@ import de.hysky.skyblocker.skyblock.item.tooltip.CompactorDeletorPreview;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.render.gui.ContainerSolver;
-import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
-import net.minecraft.client.item.TooltipContext;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@@ -58,6 +56,31 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
@Unique
private static final Identifier ITEM_PROTECTION = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/item_protection.png");
+ @Unique
+ private static final Set<String> FILLER_ITEMS = Set.of(
+ " ", // Empty menu item
+ "Locked Page",
+ "Quick Crafting Slot",
+ "Locked Backpack Slot 2", //Regular expressions won't be utilized here since the search by contains is based on plain text rather than regex syntax
+ "Locked Backpack Slot 3",
+ "Locked Backpack Slot 4",
+ "Locked Backpack Slot 5",
+ "Locked Backpack Slot 6",
+ "Locked Backpack Slot 7",
+ "Locked Backpack Slot 8",
+ "Locked Backpack Slot 9",
+ "Locked Backpack Slot 10",
+ "Locked Backpack Slot 11",
+ "Locked Backpack Slot 12",
+ "Locked Backpack Slot 13",
+ "Locked Backpack Slot 14",
+ "Locked Backpack Slot 15",
+ "Locked Backpack Slot 16",
+ "Locked Backpack Slot 17",
+ "Locked Backpack Slot 18",
+ "Preparing"
+ );
+
@Shadow
@Nullable
protected Slot focusedSlot;
@@ -84,14 +107,6 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
}
}
- @Inject(at = @At("RETURN"), method = "render")
- public void skyblocker$renderScreen(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
- if (!Utils.isOnSkyblock()) return;
-
- if (SkyblockerConfigManager.get().locations.garden.visitorHelper && (Utils.getLocationRaw().equals("garden") && !getTitle().getString().contains("Logbook") || getTitle().getString().startsWith("Bazaar")))
- VisitorHelper.renderScreen(this.getTitle().getString(), context, textRenderer, handler, mouseX, mouseY);
- }
-
@Inject(at = @At("HEAD"), method = "mouseClicked")
public void skyblocker$mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> cir) {
if (SkyblockerConfigManager.get().locations.garden.visitorHelper && (Utils.getLocationRaw().equals("garden") && !getTitle().getString().contains("Logbook") || getTitle().getString().startsWith("Bazaar")))
@@ -134,6 +149,9 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
return skyblocker$experimentSolvers$getStack(slot, stack);
}
+ /**
+ * Redirects getStack calls to account for different stacks in experiment solvers.
+ */
@Unique
private ItemStack skyblocker$experimentSolvers$getStack(Slot slot, @NotNull ItemStack stack) {
ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver();
@@ -144,115 +162,81 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen
return stack;
}
- @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().map(Map.Entry::getKey).ifPresentOrElse(ultrasequencerSolver::setUltrasequencerNextSlot, () -> ultrasequencerSolver.setState(ExperimentSolver.State.END));
- }
- }
- }
- }
-
/**
* The naming of this method in yarn is half true, its mostly to handle slot/item interactions (which are mouse or keyboard clicks)
* For example, using the drop key bind while hovering over an item will invoke this method to drop the players item
*/
- @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true)
- private void skyblocker$onSlotInteract(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) {
- if (Utils.isOnSkyblock()) {
- // When you try and drop the item by picking it up then clicking outside of the screen
- if (slotId == OUT_OF_BOUNDS_SLOT) {
- ItemStack cursorStack = this.handler.getCursorStack();
-
- if (ItemProtection.isItemProtected(cursorStack)) ci.cancel();
- }
-
- if (slot != null) {
- // Prevent some menu items from dragging and dropping
- String itemName = slot.getStack().getName().getString();
- if (SkyblockerConfigManager.get().general.hideEmptyTooltips) {
- Set<String> blockedItemPatterns = Set.of(
- " ", // Empty menu item
- "Locked Page",
- "Quick Crafting Slot",
- "Locked Backpack Slot 2", //Regular expressions won't be utilized here since the search by contains is based on plain text rather than regex syntax
- "Locked Backpack Slot 3",
- "Locked Backpack Slot 4",
- "Locked Backpack Slot 5",
- "Locked Backpack Slot 6",
- "Locked Backpack Slot 7",
- "Locked Backpack Slot 8",
- "Locked Backpack Slot 9",
- "Locked Backpack Slot 10",
- "Locked Backpack Slot 11",
- "Locked Backpack Slot 12",
- "Locked Backpack Slot 13",
- "Locked Backpack Slot 14",
- "Locked Backpack Slot 15",
- "Locked Backpack Slot 16",
- "Locked Backpack Slot 17",
- "Locked Backpack Slot 18",
- "Preparing"
- );
- if (blockedItemPatterns.contains(itemName)) {
- ci.cancel();
- }
- }
-
- // When you click your drop key while hovering over an item
- if (actionType == SlotActionType.THROW) {
- ItemStack stack = 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"), cancellable = true)
+ private void skyblocker$onSlotClick(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) {
+ if (!Utils.isOnSkyblock()) return;
- if (ItemProtection.isItemProtected(stack)) ci.cancel();
- }
+ // Item Protection
+ // When you try and drop the item by picking it up then clicking outside the screen
+ if (slotId == OUT_OF_BOUNDS_SLOT && ItemProtection.isItemProtected(this.handler.getCursorStack())) {
+ ci.cancel();
+ return;
+ }
- //Prevent salvaging
- if (this.getTitle().getString().equals("Salvage Items")) {
- ItemStack stack = slot.getStack();
+ if (slot == null) return;
+ String title = getTitle().getString();
+ ItemStack stack = skyblocker$experimentSolvers$getStack(slot, slot.getStack());
+ ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver();
- if (ItemProtection.isItemProtected(stack)) ci.cancel();
+ // Prevent clicks on filler items
+ if (SkyblockerConfigManager.get().general.hideEmptyTooltips && FILLER_ITEMS.contains(stack.getName().getString()) &&
+ // Allow clicks in Ultrasequencer and Superpairs
+ (!UltrasequencerSolver.INSTANCE.getName().matcher(title).matches() || SkyblockerConfigManager.get().general.experiments.enableUltrasequencerSolver)) {
+ ci.cancel();
+ return;
+ }
+ // Item Protection
+ // When you click your drop key while hovering over an item
+ if (actionType == SlotActionType.THROW && ItemProtection.isItemProtected(stack)) {
+ ci.cancel();
+ return;
+ }
+ // Prevent salvaging
+ if (title.equals("Salvage Items") && ItemProtection.isItemProtected(stack)) {
+ ci.cancel();
+ return;
+ }
+ if (this.handler instanceof GenericContainerScreenHandler genericContainerScreenHandler && genericContainerScreenHandler.getRows() == 6) {
+ VisitorHelper.onSlotClick(slot, slotId, title);
+
+ // Prevent selling to NPC shops
+ ItemStack sellStack = this.handler.slots.get(49).getStack();
+ if (sellStack.getName().getString().equals("Sell Item") || ItemUtils.getNbtTooltip(sellStack, text -> text.contains("buyback")) != null) {
+ if (slotId != 49 && ItemProtection.isItemProtected(stack)) {
+ ci.cancel();
+ return;
}
+ }
+ }
-
- if (this.client != null && this.handler instanceof GenericContainerScreenHandler genericContainerScreenHandler && genericContainerScreenHandler.getRows() == 6) {
- VisitorHelper.onSlotClick(slot, slotId, this.getTitle().getString());
-
- //Prevent selling to NPC shops
- ItemStack sellItem = this.handler.slots.get(49).getStack();
-
- if (sellItem.getName().getString().equals("Sell Item") || skyblocker$doesLoreContain(sellItem, this.client, "buyback")) {
- ItemStack stack = slot.getStack();
-
- if (ItemProtection.isItemProtected(stack)) ci.cancel();
- }
+ // Experiment Solvers
+ 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 ((stack.isOf(item) || ChronomatronSolver.TERRACOTTA_TO_GLASS.get(stack.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().map(Map.Entry::getKey).ifPresentOrElse(ultrasequencerSolver::setUltrasequencerNextSlot, () -> ultrasequencerSolver.setState(ExperimentSolver.State.END));
}
+ return;
}
}
- //TODO make this a util method somewhere else, eventually
- private static boolean skyblocker$doesLoreContain(ItemStack stack, MinecraftClient client, String searchString) {
- return stack.getTooltip(client.player, TooltipContext.BASIC).stream().map(Text::getString).anyMatch(line -> line.contains(searchString));
- }
-
@Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V"))
private void skyblocker$drawItemRarityBackground(DrawContext context, Slot slot, CallbackInfo ci) {
if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds)
ItemRarityBackgrounds.tryDraw(slot.getStack(), context, slot.x, slot.y);
// Item protection
- if (ItemProtection.isItemProtected(slot.getStack())){
+ if (ItemProtection.isItemProtected(slot.getStack())) {
RenderSystem.enableBlend();
context.drawTexture(ITEM_PROTECTION, slot.x, slot.y, 0, 0, 16, 16, 16, 16);
RenderSystem.disableBlend();
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 746235b7..4e87b237 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java
@@ -12,9 +12,10 @@ import java.util.List;
import java.util.Map;
public class UltrasequencerSolver extends ExperimentSolver {
+ public static final UltrasequencerSolver INSTANCE = new UltrasequencerSolver();
private int ultrasequencerNextSlot;
- public UltrasequencerSolver() {
+ private UltrasequencerSolver() {
super("^Ultrasequencer \\(\\w+\\)$");
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
index 3c049f69..4fd9eeb3 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
@@ -1,13 +1,17 @@
package de.hysky.skyblocker.skyblock.garden;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.itemlist.ItemRepository;
import de.hysky.skyblocker.utils.NEURepoManager;
+import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.scheduler.MessageScheduler;
import io.github.moulberry.repo.data.NEUItem;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
@@ -32,11 +36,20 @@ public class VisitorHelper {
private static final Map<String, ItemStack> itemCache = new HashMap<>();
private static final int TEXT_START_X = 4;
private static final int TEXT_START_Y = 4;
+ private static final int TEXT_INDENT = 8;
private static final int LINE_SPACING = 3;
+ public static void init() {
+ ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
+ String title = screen.getTitle().getString();
+ if (SkyblockerConfigManager.get().locations.garden.visitorHelper && screen instanceof HandledScreen<?> handledScreen && (Utils.getLocationRaw().equals("garden") && !title.contains("Logbook") || title.startsWith("Bazaar"))) {
+ ScreenEvents.afterRender(screen).register((screen_, context, mouseX, mouseY, delta) -> renderScreen(title, context, client.textRenderer, handledScreen.getScreenHandler(), mouseX, mouseY));
+ }
+ });
+ }
+
public static void renderScreen(String title, DrawContext context, TextRenderer textRenderer, ScreenHandler handler, int mouseX, int mouseY) {
- if (handler.getCursorStack() == ItemStack.EMPTY)
- processVisitorItem(title, handler);
+ if (handler.getCursorStack() == ItemStack.EMPTY) processVisitorItem(title, handler);
drawScreenItems(context, textRenderer, mouseX, mouseY);
}
@@ -51,9 +64,9 @@ public class VisitorHelper {
for (Object2IntMap.Entry<String> itemEntry : visitorEntry.getValue().object2IntEntrySet()) {
String itemText = itemEntry.getKey();
- textWidth = textRenderer.getWidth(itemText);
+ textWidth = textRenderer.getWidth(itemText + " x" + itemEntry.getIntValue());
- if (isMouseOverText(mouseX, mouseY, TEXT_START_X, yPosition, textWidth, textHeight)) {
+ if (isMouseOverText(mouseX, mouseY, TEXT_START_X + TEXT_INDENT, yPosition, textWidth, textHeight)) {
MessageScheduler.INSTANCE.sendMessageAfterCooldown("/bz " + itemText);
return;
}
@@ -107,6 +120,8 @@ public class VisitorHelper {
}
private static void drawScreenItems(DrawContext context, TextRenderer textRenderer, int mouseX, int mouseY) {
+ context.getMatrices().push();
+ context.getMatrices().translate(0, 0, 200);
int index = 0;
for (Map.Entry<String, Object2IntMap<String>> visitorEntry : itemMap.entrySet()) {
String visitorName = visitorEntry.getKey();
@@ -117,6 +132,7 @@ public class VisitorHelper {
index = drawItemEntryWithHover(context, textRenderer, itemEntry, index, mouseX, mouseY);
}
}
+ context.getMatrices().pop();
}
private static int drawItemEntryWithHover(DrawContext context, TextRenderer textRenderer, Map.Entry<String, Integer> itemEntry, int index, int mouseX, int mouseY) {
@@ -145,15 +161,19 @@ public class VisitorHelper {
private static void drawItemEntryWithHover(DrawContext context, TextRenderer textRenderer, ItemStack stack, int amount, int index, int mouseX, int mousseY) {
Text text = Serialization.fromJson(stack.getSubNbt("display").getString("Name")).append(" x" + amount);
- drawTextWithOptionalUnderline(context, textRenderer, text, TEXT_START_X + 8, TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), mouseX, mousseY);
- context.drawItem(stack, TEXT_START_X + 10 + textRenderer.getWidth(text), TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)) - textRenderer.fontHeight + 5);
+ drawTextWithOptionalUnderline(context, textRenderer, text, TEXT_START_X + TEXT_INDENT, TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), mouseX, mousseY);
+ // drawItem adds 150 to the z, which puts our z at 350, above the item in the slot (250) and their text (300) and below the cursor stack (382) and their text (432)
+ context.drawItem(stack, TEXT_START_X + TEXT_INDENT + 2 + textRenderer.getWidth(text), TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)) - textRenderer.fontHeight + 5);
}
private static void drawTextWithOptionalUnderline(DrawContext context, TextRenderer textRenderer, Text text, int x, int y, int mouseX, int mouseY) {
+ context.getMatrices().push();
+ context.getMatrices().translate(0, 0, 150); // This also puts our z at 350
context.drawText(textRenderer, text, x, y, -1, true);
if (isMouseOverText(mouseX, mouseY, x, y, textRenderer.getWidth(text), textRenderer.fontHeight)) {
context.drawHorizontalLine(x, x + textRenderer.getWidth(text), y + textRenderer.fontHeight, -1);
}
+ context.getMatrices().pop();
}
private static boolean isMouseOverText(double mouseX, double mouseY, int x, int y, int width, int height) {
diff --git a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java
index 60e2b4e4..f78e5184 100644
--- a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java
+++ b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java
@@ -42,7 +42,7 @@ public class ContainerSolverManager {
new CroesusHelper(),
new ChronomatronSolver(),
new SuperpairsSolver(),
- new UltrasequencerSolver()
+ UltrasequencerSolver.INSTANCE
};
}