aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorWanja <105125277+Manchick0@users.noreply.github.com>2025-01-05 03:06:40 +0100
committerGitHub <noreply@github.com>2025-01-05 10:06:40 +0800
commit8575fb83989ce783bf1faf4ca14908c4135560d0 (patch)
tree90c0ca106255c764bb0b18f773d963bb898ef941 /src/main/java
parente4ea0c5fffa16868d638c2d6cc23f610669bd5fb (diff)
downloadSkyblocker-8575fb83989ce783bf1faf4ca14908c4135560d0.tar.gz
Skyblocker-8575fb83989ce783bf1faf4ca14908c4135560d0.tar.bz2
Skyblocker-8575fb83989ce783bf1faf4ca14908c4135560d0.zip
ItemList Changes (#1119)
* ItemList changes This update introduces a bunch of changes to the ItemList feature, to hopefully enhance user experience. Most importantly, you can now filter out specific elements in the list to narrow down the results. The lore-search now works properly, and you're now able to use the wiki lookup key in the recipe book. Besides all that, shift-clicking on the recipe result button will suggest the recipe to the player using the `viewrecipe` command, to allow quick super-craft access. * Add missing GUI filter icons * Update FilterOption.java Properly use parentheses in the `(animal)` and `(pest)` flagged entries. * Refactor recipe view command to use MessageScheduler. Replaces direct chat command handling with MessageScheduler. * Refactor filtering logic and remove Identifiable interface. Replaced the Identifiable interface with a Supplier-based design for enum, updated related classes to use Supplier methods and refactored filtering logic for consistency. Additionally, added a new tip for viewing recipes in the recipe book, and changed the Shift+Click requirement to a simple right click. * Clean up the code
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/Tips.java3
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java12
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java19
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/FilterOption.java39
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/RecipeAreaDisplay.java10
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingRecipeResults.java38
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingTab.java15
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeBookWidget.java41
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeResultButton.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/UpcomingEventsTab.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/gui/CyclingTextureWidget.java77
11 files changed, 228 insertions, 32 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/Tips.java b/src/main/java/de/hysky/skyblocker/skyblock/Tips.java
index 9b95abb2..8c7e107e 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/Tips.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/Tips.java
@@ -64,7 +64,8 @@ public class Tips {
getTipFactory("skyblocker.tips.gardenMouseLock", ClickEvent.Action.SUGGEST_COMMAND, "/skyblocker config"),
getTipFactory("skyblocker.tips.newYearCakesHelper"),
getTipFactory("skyblocker.tips.accessoryHelper"),
- getTipFactory("skyblocker.tips.fancyAuctionHouseCheapHighlight")
+ getTipFactory("skyblocker.tips.fancyAuctionHouseCheapHighlight"),
+ getTipFactory("skyblocker.tips.viewRecipe")
));
private static boolean sentTip = false;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java
index ca29db16..cc0b3be8 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java
@@ -57,16 +57,12 @@ public class ItemRarityBackgrounds {
}
public static void tryDraw(ItemStack stack, DrawContext context, int x, int y) {
- MinecraftClient client = MinecraftClient.getInstance();
-
- if (client.player != null) {
- SkyblockItemRarity itemRarity = getItemRarity(stack, client.player);
-
- if (itemRarity != null) draw(context, x, y, itemRarity);
- }
+ SkyblockItemRarity itemRarity = getItemRarity(stack);
+ if (itemRarity != null)
+ draw(context, x, y, itemRarity);
}
- private static SkyblockItemRarity getItemRarity(ItemStack stack, ClientPlayerEntity player) {
+ private static SkyblockItemRarity getItemRarity(ItemStack stack) {
if (stack == null || stack.isEmpty()) return null;
String itemUuid = stack.getUuid();
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java b/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java
index 0e1c9d0e..9ebf72a6 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java
@@ -8,6 +8,7 @@ import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
@@ -33,12 +34,16 @@ public class WikiLookup {
}
public static void openWiki(@NotNull Slot slot, @NotNull PlayerEntity player) {
- ItemUtils.getItemIdOptional(slot.getStack())
- .map(ItemRepository::getWikiLink)
- .ifPresentOrElse(wikiLink -> CompletableFuture.runAsync(() -> Util.getOperatingSystem().open(wikiLink)).exceptionally(e -> {
- LOGGER.error("[Skyblocker] Error while retrieving wiki article...", e);
- player.sendMessage(Constants.PREFIX.get().append("Error while retrieving wiki article, see logs..."), false);
- return null;
- }), () -> player.sendMessage(Constants.PREFIX.get().append(Text.translatable("skyblocker.wikiLookup.noArticleFound")), false));
+ WikiLookup.openWiki(slot.getStack(), player);
}
+
+ public static void openWiki(ItemStack stack, PlayerEntity player) {
+ ItemUtils.getItemIdOptional(stack)
+ .map(ItemRepository::getWikiLink)
+ .ifPresentOrElse(wikiLink -> CompletableFuture.runAsync(() -> Util.getOperatingSystem().open(wikiLink)).exceptionally(e -> {
+ LOGGER.error("[Skyblocker] Error while retrieving wiki article...", e);
+ player.sendMessage(Constants.PREFIX.get().append("Error while retrieving wiki article, see logs..."), false);
+ return null;
+ }), () -> player.sendMessage(Constants.PREFIX.get().append(Text.translatable("skyblocker.wikiLookup.noArticleFound")), false));
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/FilterOption.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/FilterOption.java
new file mode 100644
index 00000000..1f33528d
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/FilterOption.java
@@ -0,0 +1,39 @@
+package de.hysky.skyblocker.skyblock.itemlist.recipebook;
+
+import de.hysky.skyblocker.SkyblockerMod;
+import net.minecraft.util.Identifier;
+
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+public enum FilterOption implements Supplier<Identifier>, Predicate<String> {
+
+ ALL(query -> true, Identifier.of(SkyblockerMod.NAMESPACE, "textures/gui/filter/all.png")),
+ ENTITIES(query -> query.endsWith("(monster)") || query.endsWith("(miniboss)") || query.endsWith("(boss)")
+ || query.endsWith("(animal)") || query.endsWith("(pest)") || query.endsWith("(sea creature)"),
+ Identifier.of(SkyblockerMod.NAMESPACE, "textures/gui/filter/entities.png")),
+ NPCS(query -> query.endsWith("(npc)") || query.endsWith("(rift npc)"), Identifier.of(SkyblockerMod.NAMESPACE, "textures/gui/filter/npcs.png")),
+ MAYORS(query -> query.endsWith("(mayor)") || query.endsWith("(retired mayor)"), Identifier.of(SkyblockerMod.NAMESPACE, "textures/gui/filter/mayors.png")),
+
+ // Basically a negation on everything else.
+ ITEMS(query -> !ENTITIES.test(query) && !NPCS.test(query) && !MAYORS.test(query),
+ Identifier.of(SkyblockerMod.NAMESPACE, "textures/gui/filter/items.png"));
+
+ private final Predicate<String> matchingPredicate;
+ private final Identifier texture;
+
+ FilterOption(Predicate<String> matchingPredicate, Identifier texture) {
+ this.matchingPredicate = matchingPredicate;
+ this.texture = texture;
+ }
+
+ @Override
+ public boolean test(String query) {
+ return matchingPredicate.test(query);
+ }
+
+ @Override
+ public Identifier get() {
+ return texture;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/RecipeAreaDisplay.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/RecipeAreaDisplay.java
index 36c5e500..8abc8b6a 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/RecipeAreaDisplay.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/RecipeAreaDisplay.java
@@ -15,8 +15,16 @@ public interface RecipeAreaDisplay {
boolean mouseClicked(double mouseX, double mouseY, int button);
+ default boolean keyPressed(double mouseX, double mouseY, int keyCode, int scanCode, int modifiers) {
+ return false;
+ }
+
+ default void updateSearchResults(String query, FilterOption filterOption) {
+ updateSearchResults(query, filterOption, false);
+ }
+
/**
* If this tab does not use the search bar then no-op this.
*/
- void updateSearchResults(String query);
+ void updateSearchResults(String query, FilterOption filterOption, boolean refresh);
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingRecipeResults.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingRecipeResults.java
index b06928dd..d6d7ea56 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingRecipeResults.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingRecipeResults.java
@@ -6,13 +6,17 @@ import java.util.Locale;
import com.google.common.collect.Lists;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.item.WikiLookup;
import de.hysky.skyblocker.skyblock.itemlist.ItemRepository;
import de.hysky.skyblocker.skyblock.itemlist.SkyblockCraftingRecipe;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.render.RenderHelper;
+import de.hysky.skyblocker.utils.scheduler.MessageScheduler;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.recipebook.RecipeBookResults;
import net.minecraft.client.gui.widget.ToggleButtonWidget;
import net.minecraft.component.DataComponentTypes;
@@ -181,18 +185,21 @@ public class SkyblockCraftingRecipeResults implements RecipeAreaDisplay {
* @implNote The {@code query} is always passed as lower case.
*/
@Override
- public void updateSearchResults(String query) {
- if (!query.equals(this.lastSearchQuery)) {
+ public void updateSearchResults(String query, FilterOption filterOption, boolean refresh) {
+ if (!ItemRepository.filesImported()) return;
+ if (!query.equals(this.lastSearchQuery) || refresh) {
this.lastSearchQuery = query;
this.searchResults.clear();
//Search for stacks which contain the search term
for (ItemStack stack : ItemRepository.getItems()) {
String name = stack.getName().getString().toLowerCase(Locale.ENGLISH);
+ if (!filterOption.test(name)) continue;
List<Text> lore = ItemUtils.getLore(stack);
- //TODO turn lore lowercase
- if (name.contains(query) || lore.stream().map(Text::getString).anyMatch(line -> line.contains(query))) {
+ if (name.contains(query) || lore.stream().map(Text::getString)
+ .map(string -> string.toLowerCase(Locale.ENGLISH))
+ .anyMatch(line -> line.contains(query))) {
this.searchResults.add(stack);
}
}
@@ -271,6 +278,16 @@ public class SkyblockCraftingRecipeResults implements RecipeAreaDisplay {
return true;
}
+ if (this.recipeView && button == 1) {
+ // The crafting result button
+ var result = resultButtons.get(14);
+ var rawID = ItemUtils.getItemId(result.getDisplayStack());
+ if (result.isMouseOver(mouseX, mouseY)) {
+ MessageScheduler.INSTANCE.sendMessageAfterCooldown(String.format("/viewrecipe %s", rawID), true);
+ return true;
+ }
+ }
+
for (SkyblockRecipeResultButton resultButton : this.resultButtons) {
//If the result button was clicked then try and show a recipe if there is one
//for the item
@@ -297,4 +314,17 @@ public class SkyblockCraftingRecipeResults implements RecipeAreaDisplay {
return false;
}
+
+ @Override
+ public boolean keyPressed(double mouseX, double mouseY, int keyCode, int scanCode, int modifiers) {
+ if (SkyblockerConfigManager.get().general.wikiLookup.enableWikiLookup
+ && WikiLookup.wikiLookup.matchesKey(keyCode, scanCode))
+ return this.resultButtons.stream()
+ .filter(button -> button.isMouseOver(mouseX, mouseY))
+ .findFirst().map(button -> {
+ WikiLookup.openWiki(button.getDisplayStack(), client.player);
+ return true;
+ }).orElse(false);
+ return false;
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingTab.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingTab.java
index 480c91df..953c1da1 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingTab.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingTab.java
@@ -20,7 +20,9 @@ record SkyblockCraftingTab(SkyblockRecipeBookWidget recipeBook, ItemStack icon,
@Override
public void draw(DrawContext context, int x, int y, int mouseX, int mouseY, float delta) {
+ assert recipeBook.searchField != null;
recipeBook.searchField.render(context, mouseX, mouseY, delta);
+ recipeBook.filterOption.render(context, mouseX, mouseY, delta);
results.draw(context, x, y, mouseX, mouseY, delta);
}
@@ -43,8 +45,8 @@ record SkyblockCraftingTab(SkyblockRecipeBookWidget recipeBook, ItemStack icon,
return true;
}
-
recipeBook.searchField.setFocused(false);
+ return recipeBook.filterOption.mouseClicked(mouseX, mouseY, button);
}
}
@@ -52,14 +54,19 @@ record SkyblockCraftingTab(SkyblockRecipeBookWidget recipeBook, ItemStack icon,
}
@Override
- public void updateSearchResults(String query) {
- results.updateSearchResults(query);
+ public boolean keyPressed(double mouseX, double mouseY, int keyCode, int scanCode, int modifiers) {
+ return this.results.keyPressed(mouseX, mouseY, keyCode, scanCode, modifiers);
+ }
+
+ @Override
+ public void updateSearchResults(String query, FilterOption filterOption, boolean refresh) {
+ results.updateSearchResults(query, filterOption, refresh);
}
@Override
public void initializeSearchResults(String query) {
if (ItemRepository.filesImported()) {
- updateSearchResults(query);
+ updateSearchResults(query, FilterOption.ALL);
}
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeBookWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeBookWidget.java
index f8c6872e..0390c981 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeBookWidget.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeBookWidget.java
@@ -3,6 +3,7 @@ package de.hysky.skyblocker.skyblock.itemlist.recipebook;
import java.util.List;
import java.util.Locale;
+import de.hysky.skyblocker.utils.render.gui.CyclingTextureWidget;
import net.minecraft.screen.ScreenHandler;
import org.jetbrains.annotations.Nullable;
@@ -34,8 +35,9 @@ public class SkyblockRecipeBookWidget extends RecipeBookWidget<NoopRecipeScreenH
private static final int IMAGE_HEIGHT = RecipeBookWidget.field_32409;
//Corresponds to field_32410 in RecipeBookWidget
private static final int OFFSET_X_POSITION = 86;
- //81 is the search field's width, 4 is the space between it and the toggle crafting button, and 26 is the toggle crafting button's width
- private static final int SEARCH_FIELD_WIDTH = 81 + 4 + 26;
+ // 81 is the search field's width, 4 is the space between it and the toggle crafting button, and 26 is the toggle crafting button's width, which we replace
+ // with the filtering button. 26 - 14 - 4 = 12 - 4 = 8 (The additional space left to the search field.)
+ private static final int SEARCH_FIELD_WIDTH = 81 + 4 + 8;
/**
* The tabs in the Skyblock recipe book.
*/
@@ -46,6 +48,8 @@ public class SkyblockRecipeBookWidget extends RecipeBookWidget<NoopRecipeScreenH
private final List<Pair<RecipeTab, SkyblockRecipeTabButton>> tabButtons = Lists.newArrayList();
private Pair<RecipeTab, SkyblockRecipeTabButton> currentTab;
+ protected CyclingTextureWidget<FilterOption> filterOption;
+
public SkyblockRecipeBookWidget(ScreenHandler screenHandler) {
super(new NoopRecipeScreenHandler(screenHandler.syncId), List.of());
}
@@ -72,6 +76,10 @@ public class SkyblockRecipeBookWidget extends RecipeBookWidget<NoopRecipeScreenH
//This field's name is misleading, the rectangle is actually the area of the magnifying glass icon rather than the entire search field
this.searchFieldRect = ScreenRect.of(NavigationAxis.HORIZONTAL, left + 8, this.searchField.getY(), this.searchField.getX() - left, this.searchField.getHeight());
+ this.filterOption = new CyclingTextureWidget<>(this.searchField.getRight() + 4, this.searchField.getY(), 14, 14, FilterOption.ALL);
+ this.filterOption.setCycleListener(this::refilterSearchResults);
+ this.filterOption.setTextSupplier(option -> Text.translatable("skyblocker.config.general.itemList.filter." + option.name().toLowerCase(Locale.ENGLISH)));
+
//Setup Tabs
this.tabButtons.clear();
@@ -150,6 +158,21 @@ public class SkyblockRecipeBookWidget extends RecipeBookWidget<NoopRecipeScreenH
return false;
}
+ @Override
+ public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
+ var client = MinecraftClient.getInstance();
+ if (client.isWindowFocused()) {
+ var mouse = client.mouse;
+ var window = client.getWindow();
+ var mouseX = (mouse.getX() * ((double) window.getScaledWidth() / (double) window.getWidth()));
+ var mouseY = (mouse.getY() * ((double) window.getScaledHeight() / (double) window.getHeight()));
+ if (this.currentTab.left().keyPressed(mouseX, mouseY, keyCode, scanCode, modifiers)) {
+ return true;
+ }
+ }
+ return super.keyPressed(keyCode, scanCode, modifiers);
+ }
+
/**
* Same as the super classes implementation just that it checks for our custom tabs.
*/
@@ -179,13 +202,21 @@ public class SkyblockRecipeBookWidget extends RecipeBookWidget<NoopRecipeScreenH
}
}
+ protected void refilterSearchResults(FilterOption filterOption) {
+ assert this.searchField != null;
+ String query = this.searchField.getText().toLowerCase(Locale.ENGLISH);
+ // Doesn't trigger the pirate speak check since the query wasn't changed.
+ this.currentTab.left().updateSearchResults(query, filterOption, true);
+ }
+
@Override
protected void refreshSearchResults() {
+ assert this.searchField != null;
String query = this.searchField.getText().toLowerCase(Locale.ENGLISH);
this.triggerPirateSpeakEasterEgg(query);
//Note: The rest of the query checks are implemented by the results class
- this.currentTab.left().updateSearchResults(query);
+ this.currentTab.left().updateSearchResults(query, this.filterOption.getCurrent());
}
private RecipeBookWidgetAccessor accessor() {
@@ -194,7 +225,9 @@ public class SkyblockRecipeBookWidget extends RecipeBookWidget<NoopRecipeScreenH
@Override
protected void refreshResults(boolean resetCurrentPage, boolean filteringCraftable) {
- this.currentTab.left().updateSearchResults(this.searchField.getText());
+ assert this.searchField != null;
+ this.currentTab.left().updateSearchResults(this.searchField.getText().toLowerCase(Locale.ENGLISH),
+ this.filterOption.getCurrent());
}
/**
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeResultButton.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeResultButton.java
index 769b8ac6..abd93c6b 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeResultButton.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeResultButton.java
@@ -19,7 +19,7 @@ public class SkyblockRecipeResultButton extends ClickableWidget {
private static final int SIZE = 25;
private static final int ITEM_OFFSET = 4;
- private ItemStack itemStack = null;
+ private ItemStack itemStack = ItemStack.EMPTY;
protected SkyblockRecipeResultButton() {
super(0, 0, SIZE, SIZE, ScreenTexts.EMPTY);
@@ -37,7 +37,7 @@ public class SkyblockRecipeResultButton extends ClickableWidget {
protected void clearDisplayStack() {
this.visible = false;
- this.itemStack = null;
+ this.itemStack = ItemStack.EMPTY;
}
@Override
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/UpcomingEventsTab.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/UpcomingEventsTab.java
index b19860bc..c30df294 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/UpcomingEventsTab.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/UpcomingEventsTab.java
@@ -95,7 +95,7 @@ public class UpcomingEventsTab implements RecipeTab {
}
@Override
- public void updateSearchResults(String query) {}
+ public void updateSearchResults(String query, FilterOption filterOption, boolean refresh) {}
@Override
public void initializeSearchResults(String query) {}
diff --git a/src/main/java/de/hysky/skyblocker/utils/render/gui/CyclingTextureWidget.java b/src/main/java/de/hysky/skyblocker/utils/render/gui/CyclingTextureWidget.java
new file mode 100644
index 00000000..71f23cba
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/render/gui/CyclingTextureWidget.java
@@ -0,0 +1,77 @@
+package de.hysky.skyblocker.utils.render.gui;
+
+import de.hysky.skyblocker.utils.EnumUtils;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.screen.ButtonTextures;
+import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
+import net.minecraft.client.gui.screen.narration.NarrationPart;
+import net.minecraft.client.gui.tooltip.Tooltip;
+import net.minecraft.client.gui.widget.ClickableWidget;
+import net.minecraft.client.render.RenderLayer;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * A widget designed for cycling through a set of textures, represented by an enum.
+ *
+ * @param <T> The type of the enum entries, which must be an {@link Enum} and implement {@link Supplier<Identifier>}.
+ */
+public class CyclingTextureWidget<T extends Enum<T> & Supplier<Identifier>> extends ClickableWidget {
+
+ private Function<T, Text> textSupplier = t -> Text.of(t.name());
+ private Function<T, Tooltip> tooltipSupplier = t -> Tooltip.of(Text.of(textSupplier.apply(t)));
+ private Consumer<T> onCycle = t -> {};
+ private T current;
+
+ private static final ButtonTextures BUTTON = new ButtonTextures(Identifier.ofVanilla("widget/button"),
+ Identifier.ofVanilla("widget/button_disabled"), Identifier.ofVanilla("widget/button_highlighted"));
+
+ public CyclingTextureWidget(int x, int y, int width, int height, T initial) {
+ super(x, y, width, height, Text.empty());
+ this.current = initial;
+ this.setTooltip(tooltipSupplier.apply(initial));
+ }
+
+ public void setCycleListener(Consumer<T> onCycle) {
+ this.onCycle = onCycle;
+ }
+
+ public void setTextSupplier(Function<T, Text> textSupplier) {
+ this.textSupplier = textSupplier;
+ setTooltip(tooltipSupplier.apply(getCurrent()));
+ }
+
+ public void setTooltipSupplier(Function<T, Tooltip> tooltipSupplier) {
+ this.tooltipSupplier = tooltipSupplier;
+ setTooltip(tooltipSupplier.apply(getCurrent()));
+ }
+
+ @Override
+ public void onClick(double mouseX, double mouseY) {
+ this.current = EnumUtils.cycle(current);
+ this.setTooltip(tooltipSupplier.apply(getCurrent()));
+ this.onCycle.accept(getCurrent());
+ }
+
+ @Override
+ protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
+ var button = BUTTON.get(this.active, this.isFocused());
+ context.drawGuiTexture(RenderLayer::getGuiTextured, button, this.getX(),
+ this.getY(), width, height);
+ context.drawTexture(RenderLayer::getGuiTextured, getCurrent().get(),
+ this.getX(), this.getY(), 0, 0, width, height, width, height);
+ }
+
+ @Override
+ protected void appendClickableNarrations(NarrationMessageBuilder builder) {
+ builder.put(NarrationPart.TITLE, this.textSupplier.apply(getCurrent()));
+ }
+
+ public T getCurrent() {
+ return current;
+ }
+}