aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
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;
+ }
+}