Skip to content

Commit

Permalink
Merge pull request #567 from kevinthegreat1/handled-screen-interactio…
Browse files Browse the repository at this point in the history
…n-fix

Fix clicking in Ultrasequencer
  • Loading branch information
LifeIsAParadox authored Feb 22, 2024
2 parents db29d4b + e859abe commit e572cb2
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 108 deletions.
2 changes: 2 additions & 0 deletions src/main/java/de/hysky/skyblocker/SkyblockerMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
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;
Expand Down Expand Up @@ -139,6 +140,7 @@ public void onInitializeClient() {
ItemProtection.init();
CreeperBeams.init();
Boulder.init();
VisitorHelper.init();
ItemRarityBackgrounds.init();
MuseumItemCache.init();
SecretsTracker.init();
Expand Down
184 changes: 84 additions & 100 deletions src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@
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;
Expand Down Expand Up @@ -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;
Expand All @@ -84,14 +107,6 @@ protected HandledScreenMixin(Text title) {
}
}

@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")))
Expand Down Expand Up @@ -134,6 +149,9 @@ protected HandledScreenMixin(Text title) {
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();
Expand All @@ -144,115 +162,81 @@ protected HandledScreenMixin(Text title) {
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
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+\\)$");
}

Expand Down
Loading

0 comments on commit e572cb2

Please sign in to comment.