diff options
| author | viciscat <51047087+viciscat@users.noreply.github.com> | 2024-11-26 04:49:02 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-25 22:49:02 -0500 |
| commit | 8798d5f0643fd40715d82e0ec5bd9c9efbc83ec0 (patch) | |
| tree | a807d85c7544fd767e5624739d128a6c0fe014a1 /src/main/java | |
| parent | beeb590496dd92a4f6839da9a25c49562b9cb32e (diff) | |
| download | Skyblocker-8798d5f0643fd40715d82e0ec5bd9c9efbc83ec0.tar.gz Skyblocker-8798d5f0643fd40715d82e0ec5bd9c9efbc83ec0.tar.bz2 Skyblocker-8798d5f0643fd40715d82e0ec5bd9c9efbc83ec0.zip | |
CTRL + F to search inventory (#933)
* CTRL + F to search inventory
* remake the whole thing pretty much
* comments yipee
* aaron
* extra translation
trying array map
Diffstat (limited to 'src/main/java')
4 files changed, 208 insertions, 1 deletions
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java index fa9bf376..4e890316 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java @@ -119,6 +119,34 @@ public class UIAndVisualsCategory { .build()) .build()) + // Inventory Search + .group(OptionGroup.createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.inventorySearch")) + .collapsed(true) + .option(Option.<UIAndVisualsConfig.InventorySearchConfig.EnableState>createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.inventorySearch.enabled")) + .binding(defaults.uiAndVisuals.inventorySearch.enabled, + () -> config.uiAndVisuals.inventorySearch.enabled, + newValue -> config.uiAndVisuals.inventorySearch.enabled = newValue) + .controller(ConfigUtils::createEnumCyclingListController) + .build()) + .option(Option.<Boolean>createBuilder() + .name(MinecraftClient.IS_SYSTEM_MAC ? Text.translatable("skyblocker.config.uiAndVisuals.inventorySearch.cmdK") : Text.translatable("skyblocker.config.uiAndVisuals.inventorySearch.ctrlK")) + .binding(defaults.uiAndVisuals.inventorySearch.ctrlK, + () -> config.uiAndVisuals.inventorySearch.ctrlK, + newValue -> config.uiAndVisuals.inventorySearch.ctrlK = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.inventorySearch.showClickableText")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.uiAndVisuals.inventorySearch.showClickableText.@Tooltip"))) + .binding(defaults.uiAndVisuals.inventorySearch.clickableText, + () -> config.uiAndVisuals.inventorySearch.clickableText, + newValue -> config.uiAndVisuals.inventorySearch.clickableText = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .build()) + //Title Container .group(OptionGroup.createBuilder() .name(Text.translatable("skyblocker.config.uiAndVisuals.titleContainer")) diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java index 598cbf54..755fb46e 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java @@ -38,6 +38,9 @@ public class UIAndVisualsConfig { public ItemCooldown itemCooldown = new ItemCooldown(); @SerialEntry + public InventorySearchConfig inventorySearch = new InventorySearchConfig(); + + @SerialEntry public TitleContainer titleContainer = new TitleContainer(); @SerialEntry @@ -83,6 +86,36 @@ public class UIAndVisualsConfig { public boolean enableItemCooldowns = true; } + public static class InventorySearchConfig { + @SerialEntry + public EnableState enabled = EnableState.SKYBLOCK; + + @SerialEntry + public boolean ctrlK = false; + + @SerialEntry + public boolean clickableText = false; + + public enum EnableState { + OFF, + SKYBLOCK, + EVERYWHERE; + + @Override + public String toString() { + return I18n.translate("skyblocker.config.uiAndVisuals.inventorySearch.state." + this.name()); + } + + public boolean isEnabled() { + return switch (this) { + case OFF -> false; + case SKYBLOCK -> de.hysky.skyblocker.utils.Utils.isOnSkyblock(); + case EVERYWHERE -> true; + }; + } + } + } + public static class TitleContainer { @SerialEntry public float titleContainerScale = 100; diff --git a/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java index 579c8773..fc9381b9 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java @@ -6,6 +6,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.InventorySearch; import de.hysky.skyblocker.skyblock.PetCache; import de.hysky.skyblocker.skyblock.experiment.ExperimentSolver; import de.hysky.skyblocker.skyblock.experiment.SuperpairsSolver; @@ -311,7 +312,7 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen } @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) { + private void skyblocker$drawOnItem(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 @@ -320,6 +321,11 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen context.drawTexture(RenderLayer::getGuiTextured, ITEM_PROTECTION, slot.x, slot.y, 0, 0, 16, 16, 16, 16); RenderSystem.disableBlend(); } + // Search + // Darken the slots + if (InventorySearch.isSearching() && !InventorySearch.slotMatches(slot)) { + context.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, 100, 0x88_000000); + } } @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawStackOverlay(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V")) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/InventorySearch.java b/src/main/java/de/hysky/skyblocker/skyblock/InventorySearch.java new file mode 100644 index 00000000..6ca1f236 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/InventorySearch.java @@ -0,0 +1,140 @@ +package de.hysky.skyblocker.skyblock; + +import de.hysky.skyblocker.annotations.Init; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.config.configs.UIAndVisualsConfig; +import de.hysky.skyblocker.utils.ItemUtils; +import it.unimi.dsi.fastutil.ints.Int2BooleanArrayMap; +import it.unimi.dsi.fastutil.ints.Int2BooleanMap; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.api.client.screen.v1.ScreenKeyboardEvents; +import net.fabricmc.fabric.api.client.screen.v1.Screens; +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.gui.widget.TextFieldWidget; +import net.minecraft.client.gui.widget.TextWidget; +import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.glfw.GLFW; + +public class InventorySearch { + private static HandledScreen<?> openedHandledScreen = null; + private static final Int2BooleanMap slotToMatch = new Int2BooleanArrayMap(64); + private static String search = ""; + + @Init + public static void init() { + ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + UIAndVisualsConfig.InventorySearchConfig inventorySearchConfig = SkyblockerConfigManager.get().uiAndVisuals.inventorySearch; + if (!inventorySearchConfig.enabled.isEnabled() || !(screen instanceof HandledScreen<?> handledScreen)) return; + + if (inventorySearchConfig.clickableText) Screens.getButtons(handledScreen).add(new SearchTextWidget(handledScreen)); + + ScreenKeyboardEvents.allowKeyPress(handledScreen).register((screen1, key, scancode, modifiers) -> { + if (key == (inventorySearchConfig.ctrlK ? GLFW.GLFW_KEY_K : GLFW.GLFW_KEY_F) && (modifiers & (GLFW.GLFW_MOD_CONTROL | GLFW.GLFW_MOD_SUPER)) != 0) { + InventorySearch.showSearchBar(handledScreen); + return false; + } + return true; + }); + }); + } + + public static void showSearchBar(HandledScreen<?> handledScreen) { + if (handledScreen == openedHandledScreen) return; + openedHandledScreen = handledScreen; + TextFieldWidget textFieldWidget = getTextFieldWidget(handledScreen); + Screens.getButtons(handledScreen).add(new TextWidget(0, 5, handledScreen.width, 10, Text.literal("Search Inventory"), Screens.getTextRenderer(handledScreen))); + Screens.getButtons(handledScreen).addFirst(textFieldWidget); + Screens.getButtons(handledScreen).removeIf(button -> button instanceof SearchTextWidget); // remove search text + handledScreen.setFocused(textFieldWidget); + + ScreenEvents.remove(handledScreen).register(InventorySearch::onScreenClosed); + } + + private static @NotNull TextFieldWidget getTextFieldWidget(HandledScreen<?> handledScreen) { + // Slightly modified text field widget + TextFieldWidget textFieldWidget = new TextFieldWidget(Screens.getTextRenderer(handledScreen), 120, 20, Text.literal("Search Inventory")) { + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + // Makes the widget catch all key presses (except escape) to fix closing the inventory when pressing E + // also check that the widget is focused and active + return super.keyPressed(keyCode, scanCode, modifiers) || (keyCode != GLFW.GLFW_KEY_ESCAPE && this.isNarratable() && this.isFocused()); + } + + // Unfocus when clicking outside + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (isFocused() && !clicked(mouseX, mouseY)) { + setFocused(false); + return false; + } + return super.mouseClicked(mouseX, mouseY, button); + } + }; + textFieldWidget.setPosition((handledScreen.width - textFieldWidget.getWidth()) / 2, 15); + textFieldWidget.setPlaceholder(Text.translatable("gui.socialInteractions.search_hint")); + textFieldWidget.setText(search); // Restore previous search + textFieldWidget.setChangedListener(InventorySearch::onSearchTyped); + return textFieldWidget; + } + + public static boolean isSearching() { + return openedHandledScreen != null; + } + + public static boolean slotMatches(Slot slot) { + return slotToMatch.computeIfAbsent(slot.id, i -> slot.hasStack() && + (slot.getStack().getName().getString().toLowerCase().contains(search) || ItemUtils.getLoreLineIf(slot.getStack(), s -> s.toLowerCase().contains(search)) != null)); + } + + private static void onSearchTyped(String text) { + slotToMatch.clear(); + search = text.toLowerCase(); + } + + private static void onScreenClosed(Screen screen) { + openedHandledScreen = null; + slotToMatch.clear(); + + } + + /** + * Button to open the search bar, for accessibility reasons (pojav and general preferences) + */ + private static class SearchTextWidget extends TextWidget { + + private final Text underlinedText; + private final Text normalText; + private final HandledScreen<?> screen; + private boolean hoveredState = false; + + public SearchTextWidget(HandledScreen<?> handledScreen) { + super(Text.translatable("skyblocker.inventorySearch.clickHereToSearch"), Screens.getTextRenderer(handledScreen)); + setPosition((handledScreen.width - this.getWidth()) / 2, 15); + underlinedText = getMessage().copy().formatted(Formatting.UNDERLINE); + normalText = getMessage().copy().formatted(Formatting.GRAY); + screen = handledScreen; + setMessage(normalText); + } + + @Override + public void onClick(double mouseX, double mouseY) { + InventorySearch.showSearchBar(screen); + } + + @Override + public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (isHovered() != hoveredState) { + hoveredState = active = isHovered(); + if (hoveredState) setMessage(underlinedText); + else setMessage(normalText); + } + + super.renderWidget(context, mouseX, mouseY, delta); + } + } +} |
