diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java index c5316ed966..44d4401194 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java @@ -3,11 +3,14 @@ import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.display.DisplaySerializer; import me.shedaniel.rei.api.common.entry.EntryIngredient; import me.shedaniel.rei.api.common.util.EntryStacks; import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Optional; /** * Skyblock Crafting Recipe display class for REI @@ -40,4 +43,14 @@ public SkyblockRecipe getRecipe() { public CategoryIdentifier getCategoryIdentifier() { return CategoryIdentifier.of(category); } + + @Override + public Optional getDisplayLocation() { + return Optional.empty(); + } + + @Override + public @Nullable DisplaySerializer getSerializer() { + return null; + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemListTab.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemListTab.java deleted file mode 100644 index 3493216bb0..0000000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemListTab.java +++ /dev/null @@ -1,93 +0,0 @@ -package de.hysky.skyblocker.skyblock.itemlist; - -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; - -import java.util.List; - -@Deprecated(forRemoval = true) -public class ItemListTab extends ItemListWidget.TabContainerWidget { - - private SearchResultsWidget results; - private final MinecraftClient client; - private TextFieldWidget searchField; - - public ItemListTab(int x, int y, MinecraftClient client, TextFieldWidget searchField) { - super(x, y, Text.literal("Item List Tab")); - this.client = client; - this.searchField = searchField; - if (ItemRepository.filesImported()) { - this.results = new SearchResultsWidget(this.client, x - 9, y - 9 ); - this.results.updateSearchResult(searchField == null ? "": this.searchField.getText()); - } - } - - @Override - public List children() { - return List.of(results, searchField); - } - - @Override - protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { - MatrixStack matrices = context.getMatrices(); - matrices.push(); - matrices.translate(0.0D, 0.0D, 100.0D); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - int x = getX(); - int y = getY(); - - // all coordinates offseted -9 - if (!ItemRepository.filesImported() && !this.searchField.isFocused() && this.searchField.getText().isEmpty()) { - Text hintText = (Text.literal("Loading...")).formatted(Formatting.ITALIC).formatted(Formatting.GRAY); - context.drawTextWithShadow(this.client.textRenderer, hintText, x + 16, y + 7, -1); - } else if (!this.searchField.isFocused() && this.searchField.getText().isEmpty()) { - Text hintText = (Text.translatable("gui.recipebook.search_hint")).formatted(Formatting.ITALIC).formatted(Formatting.GRAY); - context.drawTextWithShadow(this.client.textRenderer, hintText, x + 16, y + 7, -1); - } else { - this.searchField.render(context, mouseX, mouseY, delta); - } - if (ItemRepository.filesImported()) { - if (results == null) { - this.results = new SearchResultsWidget(this.client, x - 9, y - 9); - } - this.results.updateSearchResult(this.searchField.getText()); - this.results.render(context, mouseX, mouseY, delta); - } - matrices.pop(); - } - - @Override - protected void appendClickableNarrations(NarrationMessageBuilder builder) {} - - public void setSearchField(TextFieldWidget searchField) { - this.searchField = searchField; - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (!visible) return false; - if (this.searchField.mouseClicked(mouseX, mouseY, button) && this.results != null) { - this.results.closeRecipeView(); - this.searchField.setFocused(true); - return true; - } else if (results != null) { - this.searchField.setFocused(false); - - return this.results.mouseClicked(mouseX, mouseY, button); - } - - return false; - } - - @Override - public void drawTooltip(DrawContext context, int mouseX, int mouseY) { - if (this.results != null) this.results.drawTooltip(context, mouseX, mouseY); - } -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemListWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemListWidget.java deleted file mode 100644 index 62458c0da6..0000000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemListWidget.java +++ /dev/null @@ -1,136 +0,0 @@ -package de.hysky.skyblocker.skyblock.itemlist; - -import de.hysky.skyblocker.mixins.accessors.RecipeBookWidgetAccessor; -import de.hysky.skyblocker.utils.render.gui.SideTabButtonWidget; -import it.unimi.dsi.fastutil.Pair; -import it.unimi.dsi.fastutil.objects.ObjectObjectImmutablePair; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.gui.widget.ContainerWidget; -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.screen.AbstractRecipeScreenHandler; -import net.minecraft.text.Text; - -import java.util.ArrayList; -import java.util.List; - -@Environment(value = EnvType.CLIENT) -@Deprecated(forRemoval = true) -public class ItemListWidget /*extends RecipeBookWidget*/ { - /*private int parentWidth; - private int parentHeight; - private int leftOffset; - - private TabContainerWidget currentTabContent; - private final List> tabs = new ArrayList<>(2); - private ItemListTab itemListTab; - - private static int currentTab = 0; - - public ItemListWidget() { - super(); - } - - @Override - public void initialize(int parentWidth, int parentHeight, MinecraftClient client, boolean narrow, AbstractRecipeScreenHandler craftingScreenHandler) { - super.initialize(parentWidth, parentHeight, client, narrow, craftingScreenHandler); - this.parentWidth = parentWidth; - this.parentHeight = parentHeight; - this.leftOffset = narrow ? 0 : 86; - TextFieldWidget searchField = ((RecipeBookWidgetAccessor) this).getSearchField(); - int x = (parentWidth - 147) / 2 - leftOffset; - int y = (parentHeight - 166) / 2; - - // Init all the tabs, content and the tab button on the left - tabs.clear(); - - // Item List - itemListTab = new ItemListTab(x + 9, y + 9, this.client, searchField); - SideTabButtonWidget itemListTabButton = new SideTabButtonWidget(x - 30, y + 3, currentTab == 0, new ItemStack(Items.CRAFTING_TABLE)); - itemListTabButton.setTooltip(Tooltip.of(Text.literal("Item List"))); - if (currentTab == 0) currentTabContent = itemListTab; - tabs.add(new ObjectObjectImmutablePair<>( - itemListTabButton, - this.itemListTab)); - - // Upcoming Events - UpcomingEventsTab upcomingEventsTab = new UpcomingEventsTab(x + 9, y + 9, this.client); - SideTabButtonWidget eventsTabButtonWidget = new SideTabButtonWidget(x - 30, y + 3 + 27, currentTab == 1, new ItemStack(Items.CLOCK)); - eventsTabButtonWidget.setTooltip(Tooltip.of(Text.literal("Upcoming Events"))); - if (currentTab == 1) currentTabContent = upcomingEventsTab; - tabs.add(new ObjectObjectImmutablePair<>( - eventsTabButtonWidget, - upcomingEventsTab - )); - - } - - @Override - public void reset() { - super.reset(); - if (itemListTab != null) itemListTab.setSearchField(((RecipeBookWidgetAccessor) this).getSearchField()); - } - - @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - if (this.isOpen()) { - int i = (this.parentWidth - 147) / 2 - this.leftOffset; - int j = (this.parentHeight - 166) / 2; - // Draw the texture - context.drawTexture(TEXTURE, i, j, 1, 1, 147, 166); - // Draw the tab's content - if (currentTabContent != null) currentTabContent.render(context, mouseX, mouseY, delta); - // Draw the tab buttons - for (Pair tab : tabs) { - tab.left().render(context, mouseX, mouseY, delta); - } - - } - } - - @Override - public void drawTooltip(DrawContext context, int x, int y, int mouseX, int mouseY) { - if (this.isOpen() && currentTabContent != null) { - this.currentTabContent.drawTooltip(context, mouseX, mouseY); - } - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (this.isOpen() && this.client.player != null && !this.client.player.isSpectator()) { - // check if a tab is clicked - for (Pair tab : tabs) { - if (tab.first().mouseClicked(mouseX, mouseY, button) && currentTabContent != tab.right()) { - for (Pair tab2 : tabs) { - tab2.first().setToggled(false); - } - tab.first().setToggled(true); - currentTabContent = tab.right(); - currentTab = tabs.indexOf(tab); - return true; - } - } - // click the tab content - if (currentTabContent != null) return currentTabContent.mouseClicked(mouseX, mouseY, button); - else return false; - } else return false; - }*/ - - /** - * A container widget but with a fixed width and height and a drawTooltip method to implement - */ - public abstract static class TabContainerWidget extends ContainerWidget { - - public TabContainerWidget(int x, int y, Text text) { - super(x, y, 131, 150, text); - } - - public abstract void drawTooltip(DrawContext context, int mouseX, int mouseY); - } -} \ No newline at end of file diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ResultButtonWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ResultButtonWidget.java deleted file mode 100644 index 91c7a7bc9a..0000000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ResultButtonWidget.java +++ /dev/null @@ -1,53 +0,0 @@ -package de.hysky.skyblocker.skyblock.itemlist; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; -import net.minecraft.client.gui.widget.ClickableWidget; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.item.ItemStack; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; - -import java.util.List; - -@Deprecated(forRemoval = true) -public class ResultButtonWidget extends ClickableWidget { - private static final Identifier BACKGROUND_TEXTURE = Identifier.ofVanilla("recipe_book/slot_craftable"); - - protected ItemStack itemStack = null; - - public ResultButtonWidget(int x, int y) { - super(x, y, 25, 25, Text.literal("")); - } - - protected void setItemStack(ItemStack itemStack) { - this.active = !itemStack.isEmpty(); - this.visible = true; - this.itemStack = itemStack; - } - - protected void clearItemStack() { - this.visible = false; - this.itemStack = null; - } - - @Override - public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { - MinecraftClient client = MinecraftClient.getInstance(); - context.drawGuiTexture(RenderLayer::getGuiTextured, BACKGROUND_TEXTURE, this.getX(), this.getY(), this.getWidth(), this.getHeight()); - context.drawItem(this.itemStack, this.getX() + 4, this.getY() + 4); - context.drawStackOverlay(client.textRenderer, itemStack, this.getX() + 4, this.getY() + 4); - } - - public void renderTooltip(DrawContext context, int mouseX, int mouseY) { - MinecraftClient client = MinecraftClient.getInstance(); - if (client.currentScreen == null) return; - List tooltip = Screen.getTooltipFromItem(client, this.itemStack); - client.currentScreen.setTooltip(tooltip.stream().map(Text::asOrderedText).toList()); - } - - @Override - protected void appendClickableNarrations(NarrationMessageBuilder builder) {} -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java deleted file mode 100644 index 84f5a71cc3..0000000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java +++ /dev/null @@ -1,275 +0,0 @@ -package de.hysky.skyblocker.skyblock.itemlist; - -import com.mojang.blaze3d.systems.RenderSystem; -import de.hysky.skyblocker.SkyblockerMod; -import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe; -import de.hysky.skyblocker.utils.ItemUtils; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.Drawable; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.ScreenPos; -import net.minecraft.client.gui.screen.ButtonTextures; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ToggleButtonWidget; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.LoreComponent; -import net.minecraft.item.ItemStack; -import net.minecraft.text.OrderedText; -import net.minecraft.text.StringVisitable; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.minecraft.util.Language; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -@Deprecated(forRemoval = true) -public class SearchResultsWidget implements Drawable, Element { - private static final ButtonTextures PAGE_FORWARD_TEXTURES = new ButtonTextures(Identifier.ofVanilla("recipe_book/page_forward"), Identifier.ofVanilla("recipe_book/page_forward_highlighted")); - private static final ButtonTextures PAGE_BACKWARD_TEXTURES = new ButtonTextures(Identifier.ofVanilla("recipe_book/page_backward"), Identifier.ofVanilla("recipe_book/page_backward_highlighted")); - private static final Identifier SLOT_TEXTURE = Identifier.ofVanilla("container/slot"); - private static final Identifier ARROW_TEXTURE = Identifier.of(SkyblockerMod.NAMESPACE, "arrow"); - private static final int COLS = 5; - private static final int MAX_TEXT_WIDTH = 124; - private static final String ELLIPSIS = "..."; - - private final MinecraftClient client; - private final int parentX; - private final int parentY; - - private final List searchResults = new ArrayList<>(); - private List recipeResults = new ArrayList<>(); - private String searchText = null; - private final List resultButtons = new ArrayList<>(); - private final List recipeSlots = new ArrayList<>(); - private final ToggleButtonWidget nextPageButton; - private final ToggleButtonWidget prevPageButton; - private int currentPage = 0; - private int pageCount = 0; - private boolean displayRecipes = false; - - public SearchResultsWidget(MinecraftClient client, int parentX, int parentY) { - this.client = client; - this.parentX = parentX; - this.parentY = parentY; - int gridX = parentX + 11; - int gridY = parentY + 31; - int rows = 4; - for (int i = 0; i < rows; ++i) - for (int j = 0; j < COLS; ++j) { - int x = gridX + j * 25; - int y = gridY + i * 25; - resultButtons.add(new ResultButtonWidget(x, y)); - } - this.nextPageButton = new ToggleButtonWidget(parentX + 93, parentY + 137, 12, 17, false); - this.nextPageButton.setTextures(PAGE_FORWARD_TEXTURES); - this.prevPageButton = new ToggleButtonWidget(parentX + 38, parentY + 137, 12, 17, true); - this.prevPageButton.setTextures(PAGE_BACKWARD_TEXTURES); - } - - public void closeRecipeView() { - this.currentPage = 0; - this.pageCount = (this.searchResults.size() - 1) / resultButtons.size() + 1; - this.displayRecipes = false; - this.updateButtons(); - } - - protected void updateSearchResult(String searchText) { - searchText = searchText.toLowerCase(Locale.ENGLISH); - - if (!searchText.equals(this.searchText)) { - this.searchText = searchText; - this.searchResults.clear(); - for (ItemStack entry : ItemRepository.getItems()) { - String name = entry.getName().toString().toLowerCase(Locale.ENGLISH); - LoreComponent lore = entry.getOrDefault(DataComponentTypes.LORE, LoreComponent.DEFAULT); - if (name.contains(this.searchText) || lore.lines().stream().map(Text::getString).anyMatch(s -> s.contains(this.searchText))) - this.searchResults.add(entry); - } - this.currentPage = 0; - this.pageCount = (this.searchResults.size() - 1) / resultButtons.size() + 1; - this.displayRecipes = false; - this.updateButtons(); - } - } - - private void updateButtons() { - recipeSlots.clear(); - if (this.displayRecipes) { - SkyblockRecipe recipe = this.recipeResults.get(this.currentPage); - for (ResultButtonWidget button : resultButtons) - button.clearItemStack(); - recipeSlots.addAll(recipe.getInputSlots(125, 75)); - recipeSlots.addAll(recipe.getOutputSlots(125, 75)); - } else { - for (int i = 0; i < resultButtons.size(); ++i) { - int index = this.currentPage * resultButtons.size() + i; - if (index < this.searchResults.size()) { - resultButtons.get(i).setItemStack(this.searchResults.get(index)); - } else { - resultButtons.get(i).clearItemStack(); - } - } - } - this.prevPageButton.active = this.currentPage > 0; - this.nextPageButton.active = this.currentPage < this.pageCount - 1; - } - - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - RenderSystem.disableDepthTest(); - if (this.displayRecipes) { - //Craft text - usually a requirement for the recipe - SkyblockRecipe recipe = this.recipeResults.get(this.currentPage); - Text craftText = recipe.getExtraText(); - if (textRenderer.getWidth(craftText) > MAX_TEXT_WIDTH) { - drawTooltip(textRenderer, context, craftText, this.parentX + 11, this.parentY + 31 + 100 - 9, mouseX, mouseY); - craftText = Text.of(textRenderer.trimToWidth(craftText, MAX_TEXT_WIDTH) + ELLIPSIS); - } - context.drawTextWithShadow(textRenderer, craftText, this.parentX + 11, this.parentY + 31 + 100 - 9, 0xffffffff); - - // Recipe category - Text category = Text.translatable("emi.category.skyblocker." + recipe.getCategoryIdentifier().getPath()); - context.drawTextWithShadow(textRenderer, category, this.parentX + 11, this.parentY + 31, -1); - - //Item name - // TODO fix if we add recipes with multiple outputs - Text resultText = recipe.getOutputs().getFirst().getName(); - if (textRenderer.getWidth(resultText) > MAX_TEXT_WIDTH) { - drawTooltip(textRenderer, context, resultText, this.parentX + 11, this.parentY + 43, mouseX, mouseY); - StringVisitable trimmed = StringVisitable.concat(textRenderer.trimToWidth(resultText, MAX_TEXT_WIDTH), StringVisitable.plain(ELLIPSIS)); - OrderedText ordered = Language.getInstance().reorder(trimmed); - - context.drawTextWithShadow(textRenderer, ordered, this.parentX + 11, this.parentY + 43, 0xffffffff); - } else { - context.drawTextWithShadow(textRenderer, resultText, this.parentX + 11, this.parentY + 43, 0xffffffff); - } - - MatrixStack matrices = context.getMatrices(); - matrices.push(); - matrices.translate(parentX + 11, parentY + 31 + 25, 0); - for (SkyblockRecipe.RecipeSlot recipeSlot : recipeSlots) { - if (recipeSlot.showBackground()) context.drawGuiTexture(SLOT_TEXTURE, recipeSlot.x(), recipeSlot.y(), 18, 18); - context.drawItem(recipeSlot.stack(), recipeSlot.x() + 1, recipeSlot.y() + 1); - } - - ScreenPos arrowLocation = recipe.getArrowLocation(125, 75); - if (arrowLocation != null) context.drawGuiTexture(ARROW_TEXTURE, arrowLocation.x(), arrowLocation.y(), 24, 16); - - recipe.render(context, 125, 75, mouseX, mouseY); - - matrices.pop(); - } - for (ResultButtonWidget button : resultButtons) - button.render(context, mouseX, mouseY, delta); - if (this.pageCount > 1) { - String string = (this.currentPage + 1) + "/" + this.pageCount; - int dx = this.client.textRenderer.getWidth(string) / 2; - context.drawText(textRenderer, string, this.parentX - dx + 73, this.parentY + 141, -1, false); - } - if (this.prevPageButton.active) this.prevPageButton.render(context, mouseX, mouseY, delta); - if (this.nextPageButton.active) this.nextPageButton.render(context, mouseX, mouseY, delta); - RenderSystem.enableDepthTest(); - } - - /** - * Used for drawing tooltips over truncated text - */ - private void drawTooltip(TextRenderer textRenderer, DrawContext context, Text text, int textX, int textY, int mouseX, int mouseY){ - RenderSystem.disableDepthTest(); - if (mouseX >= textX && mouseX <= textX + MAX_TEXT_WIDTH + 4 && mouseY >= textY && mouseY <= textY + 9) { - context.drawTooltip(textRenderer, text, mouseX, mouseY); - } - RenderSystem.enableDepthTest(); - } - - /** - * @see #drawTooltip(TextRenderer, DrawContext, Text, int, int, int, int) - */ - private void drawTooltip(TextRenderer textRenderer, DrawContext context, String text, int textX, int textY, int mouseX, int mouseY){ - drawTooltip(textRenderer, context, Text.of(text), textX, textY, mouseX, mouseY); - } - - public void drawTooltip(DrawContext context, int mouseX, int mouseY) { - RenderSystem.disableDepthTest(); - for (ResultButtonWidget button : resultButtons) - if (button.isMouseOver(mouseX, mouseY)) - button.renderTooltip(context, mouseX, mouseY); - for (SkyblockRecipe.RecipeSlot recipeSlot : recipeSlots) { - int shiftedMouseX = mouseX - parentX - 11; - int shiftedMouseY = mouseY - parentY - 31 - 25; - if (isMouseOverSlot(recipeSlot, shiftedMouseX, shiftedMouseY)) { - MinecraftClient client = MinecraftClient.getInstance(); - if (client.currentScreen == null) continue; - List tooltip = Screen.getTooltipFromItem(client, recipeSlot.stack()); - client.currentScreen.setTooltip(tooltip.stream().map(Text::asOrderedText).toList()); - } - } - RenderSystem.enableDepthTest(); - } - - public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { - for (ResultButtonWidget button : resultButtons) { - if (button.mouseClicked(mouseX, mouseY, mouseButton)) { - String internalName = ItemUtils.getItemId(button.itemStack); - if (internalName.isEmpty()) { - continue; - } - fetchRecipesAndUpdate(button.itemStack); - return true; - } - } - for (SkyblockRecipe.RecipeSlot recipeSlot : recipeSlots) { - int shiftedMouseX = (int) (mouseX - parentX - 11); - int shiftedMouseY = (int) (mouseY - parentY - 31 - 25); - if (isMouseOverSlot(recipeSlot, shiftedMouseX, shiftedMouseY)) { - - fetchRecipesAndUpdate(recipeSlot.stack()); - return true; - } - } - if (this.prevPageButton.mouseClicked(mouseX, mouseY, mouseButton)) { - --this.currentPage; - this.updateButtons(); - return true; - } - if (this.nextPageButton.mouseClicked(mouseX, mouseY, mouseButton)) { - ++this.currentPage; - this.updateButtons(); - return true; - } - return false; - } - - private static boolean isMouseOverSlot(SkyblockRecipe.RecipeSlot recipeSlot, int mouseX, int mouseY) { - return recipeSlot.x() <= mouseX && mouseX < recipeSlot.x() + 18 && recipeSlot.y() <= mouseY && mouseY < recipeSlot.y() + 18; - } - - private void fetchRecipesAndUpdate(ItemStack recipeSlot) { - List recipes = ItemRepository.getRecipesAndUsages(recipeSlot); - if (!recipes.isEmpty()) { - this.recipeResults = recipes; - this.currentPage = 0; - this.pageCount = recipes.size(); - this.displayRecipes = true; - this.updateButtons(); - } - } - - private boolean focused = false; - - @Override - public void setFocused(boolean focused) { - this.focused = focused; - } - - @Override - public boolean isFocused() { - return focused; - } - -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/UpcomingEventsTab.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/UpcomingEventsTab.java deleted file mode 100644 index f59fe809a5..0000000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/UpcomingEventsTab.java +++ /dev/null @@ -1,168 +0,0 @@ -package de.hysky.skyblocker.skyblock.itemlist; - -import de.hysky.skyblocker.mixins.accessors.DrawContextInvoker; -import de.hysky.skyblocker.skyblock.events.EventNotifications; -import de.hysky.skyblocker.skyblock.tabhud.widget.JacobsContestWidget; -import de.hysky.skyblocker.utils.SkyblockTime; -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.Element; -import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; -import net.minecraft.client.gui.tooltip.HoveredTooltipPositioner; -import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.text.MutableText; -import net.minecraft.text.Style; -import net.minecraft.text.Text; -import net.minecraft.util.Colors; -import net.minecraft.util.Formatting; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.List; - -@Deprecated(forRemoval = true) -public class UpcomingEventsTab extends ItemListWidget.TabContainerWidget { - private static final ItemStack CLOCK = new ItemStack(Items.CLOCK); - private final MinecraftClient client; - private final List events; - - public UpcomingEventsTab(int x, int y, MinecraftClient client) { - super(x, y, Text.literal("Upcoming Events Tab")); - this.client = client; - events = EventNotifications.getEvents().entrySet() - .stream() - .sorted(Comparator.comparingLong(a -> a.getValue().isEmpty() ? Long.MAX_VALUE : a.getValue().peekFirst().start())) - .map(stringLinkedListEntry -> new EventRenderer(stringLinkedListEntry.getKey(), stringLinkedListEntry.getValue())) - .toList(); - } - - @Override - public void drawTooltip(DrawContext context, int mouseX, int mouseY) { - if (hovered != null) { - ((DrawContextInvoker) context).invokeDrawTooltip(this.client.textRenderer, hovered.getTooltip(), mouseX, mouseY, HoveredTooltipPositioner.INSTANCE, null); - } - } - - @Override - public List children() { - return List.of(); - } - - private EventRenderer hovered = null; - - @Override - protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { - int x = getX(); - int y = getY(); - context.enableScissor(x, y, getRight(), getBottom()); - context.drawItem(CLOCK, x, y + 4); - context.drawText(this.client.textRenderer, "Upcoming Events", x + 17, y + 7, -1, true); - - int eventsY = y + 7 + 24; - hovered = null; - for (EventRenderer eventRenderer : events) { - eventRenderer.render(context, x + 1, eventsY, mouseX, mouseY); - if (isMouseOver(mouseX, mouseY) && eventRenderer.isMouseOver(mouseX, mouseY, x+1, eventsY)) hovered = eventRenderer; - eventsY += eventRenderer.getHeight(); - - } - context.disableScissor(); - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (hovered != null && hovered.getWarpCommand() != null) { - MessageScheduler.INSTANCE.sendMessageAfterCooldown(hovered.getWarpCommand()); - return true; - } - return false; - } - - @Override - protected void appendClickableNarrations(NarrationMessageBuilder builder) { - - } - - public static class EventRenderer { - - private final LinkedList events; - private final String eventName; - - public EventRenderer(String eventName, LinkedList events) { - this.events = events; - this.eventName = eventName; - } - - public void render(DrawContext context, int x, int y, int mouseX, int mouseY) { - long time = System.currentTimeMillis() / 1000; - TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - context.drawText(textRenderer, Text.literal(eventName).fillStyle(Style.EMPTY.withUnderline(isMouseOver(mouseX, mouseY, x, y))), x, y, -1, true); - if (events.isEmpty()) { - context.drawText(textRenderer, Text.literal(" ").append(Text.translatable("skyblocker.events.tab.noMore")), x, y + textRenderer.fontHeight, Colors.GRAY, false); - } else if (events.peekFirst().start() > time) { - MutableText formatted = Text.literal(" ").append(Text.translatable("skyblocker.events.tab.startsIn", SkyblockTime.formatTime((int) (events.peekFirst().start() - time)))).formatted(Formatting.YELLOW); - context.drawText(textRenderer, formatted, x, y + textRenderer.fontHeight, -1, true); - } else { - MutableText formatted = Text.literal(" ").append(Text.translatable( "skyblocker.events.tab.endsIn", SkyblockTime.formatTime((int) (events.peekFirst().start() + events.peekFirst().duration() - time)))).formatted(Formatting.GREEN); - context.drawText(textRenderer, formatted, x, y + textRenderer.fontHeight, -1, true); - } - - } - - public int getHeight() { - return 20; - } - - public boolean isMouseOver(int mouseX, int mouseY, int x, int y) { - return mouseX >= x && mouseX <= x + 131 && mouseY >= y && mouseY <= y+getHeight(); - } - - public List getTooltip() { - List components = new ArrayList<>(); - if (events.peekFirst() == null) return components; - if (eventName.equals(EventNotifications.JACOBS)) { - components.add(new JacobsTooltip(events.peekFirst().extras())); - } - //noinspection DataFlowIssue - if (events.peekFirst().warpCommand() != null) { - components.add(TooltipComponent.of(Text.translatable("skyblocker.events.tab.clickToWarp").formatted(Formatting.ITALIC).asOrderedText())); - } - - return components; - } - - public @Nullable String getWarpCommand() { - if (events.isEmpty()) return null; - return events.peek().warpCommand(); - } - } - - private record JacobsTooltip(String[] crops) implements TooltipComponent { - private static final ItemStack BARRIER = new ItemStack(Items.BARRIER); - - @Override - public int getHeight(TextRenderer textRenderer) { - return 20; - } - - @Override - public int getWidth(TextRenderer textRenderer) { - return 16 * 3 + 4; - } - - @Override - public void drawItems(TextRenderer textRenderer, int x, int y, int width, int height, DrawContext context) { - for (int i = 0; i < crops.length; i++) { - String crop = crops[i]; - context.drawItem(JacobsContestWidget.FARM_DATA.getOrDefault(crop, BARRIER), x + 18 * i, y + 2); - } - } - - } -} 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 480c91df66..e979b5043d 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 @@ -10,7 +10,7 @@ /** * The Skyblock Crafting Tab which handles the mouse clicks & rendering for the results page and the search field. */ -record SkyblockCraftingTab(SkyblockRecipeBookWidget recipeBook, ItemStack icon, SkyblockCraftingRecipeResults results) implements RecipeTab { +record SkyblockCraftingTab(SkyblockRecipeBookWidget recipeBook, ItemStack icon, SkyblockRecipeResults results) implements RecipeTab { static final ItemStack CRAFTING_TABLE = new ItemStack(Items.CRAFTING_TABLE); @Override 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 f8c6872e64..192bfaa1cb 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 @@ -40,7 +40,7 @@ public class SkyblockRecipeBookWidget extends RecipeBookWidget tabs = List.of( - new SkyblockCraftingTab(this, SkyblockCraftingTab.CRAFTING_TABLE, new SkyblockCraftingRecipeResults()), + new SkyblockCraftingTab(this, SkyblockCraftingTab.CRAFTING_TABLE, new SkyblockRecipeResults()), new UpcomingEventsTab() ); private final List> tabButtons = Lists.newArrayList(); 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 769b8ac647..07b9fb9cd2 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 @@ -13,6 +13,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; public class SkyblockRecipeResultButton extends ClickableWidget { //Corresponds to AnimatedResultButton#field_32415 @@ -25,14 +26,20 @@ protected SkyblockRecipeResultButton() { super(0, 0, SIZE, SIZE, ScreenTexts.EMPTY); } - protected ItemStack getDisplayStack() { + protected SkyblockRecipeResultButton(int x, int y) { + this(); + setPosition(x, y); + } + + protected @Nullable ItemStack getDisplayStack() { return this.itemStack; } - protected void setDisplayStack(ItemStack stack) { + protected SkyblockRecipeResultButton setDisplayStack(ItemStack stack) { this.active = !stack.isEmpty(); this.visible = true; this.itemStack = stack; + return this; } protected void clearDisplayStack() { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingRecipeResults.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeResults.java similarity index 74% rename from src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingRecipeResults.java rename to src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeResults.java index b06928dd66..7a3cc66b2b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockCraftingRecipeResults.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipebook/SkyblockRecipeResults.java @@ -7,7 +7,9 @@ import com.google.common.collect.Lists; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; -import de.hysky.skyblocker.skyblock.itemlist.SkyblockCraftingRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockForgeRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.render.RenderHelper; import net.minecraft.client.MinecraftClient; @@ -17,18 +19,21 @@ import net.minecraft.client.gui.widget.ToggleButtonWidget; import net.minecraft.component.DataComponentTypes; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.OrderedText; import net.minecraft.text.StringVisitable; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Language; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector2i; //TODO when in recipe view set search hint to talk about close or smth /** * Based off {@link net.minecraft.client.gui.screen.recipebook.RecipeBookResults}. */ -public class SkyblockCraftingRecipeResults implements RecipeAreaDisplay { +public class SkyblockRecipeResults implements RecipeAreaDisplay { /** * The width before text will go outside of the recipe book area. */ @@ -36,6 +41,8 @@ public class SkyblockCraftingRecipeResults implements RecipeAreaDisplay { private static final String ELLIPSIS_STRING = ScreenTexts.ELLIPSIS.getString(); private final List resultButtons = Lists.newArrayListWithCapacity(20); + private final List recipeSlotButtons = Lists.newArrayListWithCapacity(16); + private @Nullable ItemStack recipeIcon = null; private MinecraftClient client; private ToggleButtonWidget nextPageButton; private ToggleButtonWidget prevPageButton; @@ -46,7 +53,7 @@ public class SkyblockCraftingRecipeResults implements RecipeAreaDisplay { * Text to be displayed as a tooltip. */ private Text hoveredText; - private List recipeResults = new ArrayList<>(); + private List recipeResults = new ArrayList<>(); private int pageCount = 0; private int currentPage = 0; /** @@ -54,7 +61,7 @@ public class SkyblockCraftingRecipeResults implements RecipeAreaDisplay { */ private boolean recipeView = false; - protected SkyblockCraftingRecipeResults() { + protected SkyblockRecipeResults() { for (int i = 0; i < 20; i++) { this.resultButtons.add(new SkyblockRecipeResultButton()); } @@ -99,12 +106,14 @@ public void draw(DrawContext context, int x, int y, int mouseX, int mouseY, floa //Render the results this.hoveredResultButton = null; - for (SkyblockRecipeResultButton resultButton : resultButtons) { + for (SkyblockRecipeResultButton resultButton : recipeView ? recipeSlotButtons : resultButtons) { resultButton.render(context, mouseX, mouseY, delta); if (resultButton.visible && resultButton.isSelected()) this.hoveredResultButton = resultButton; } + + //Render the page flip buttons if (this.prevPageButton.active) this.prevPageButton.render(context, mouseX, mouseY, delta); if (this.nextPageButton.active) this.nextPageButton.render(context, mouseX, mouseY, delta); @@ -113,7 +122,7 @@ public void draw(DrawContext context, int x, int y, int mouseX, int mouseY, floa //TODO enable scissor? private void drawRecipeDisplay(DrawContext context, TextRenderer textRenderer, int x, int y, int mouseX, int mouseY) { //Render the "Craft Text" which is usually a requirement (e.g. Wolf Slayer 7) - String craftText = this.recipeResults.get(this.currentPage).getCraftText(); + String craftText = this.recipeResults.get(this.currentPage).getExtraText().getString(); if (!craftText.isEmpty()) { if (textRenderer.getWidth(craftText) > MAX_TEXT_WIDTH) { @@ -127,7 +136,7 @@ private void drawRecipeDisplay(DrawContext context, TextRenderer textRenderer, i } //Render the resulting item's name - Text itemName = this.recipeResults.get(this.currentPage).getResult().getName(); + Text itemName = this.recipeResults.get(this.currentPage).getOutputs().getFirst().getName(); if (textRenderer.getWidth(itemName) > MAX_TEXT_WIDTH) { StringVisitable trimmed = StringVisitable.concat(textRenderer.trimToWidth(itemName, MAX_TEXT_WIDTH), ScreenTexts.ELLIPSIS); @@ -143,6 +152,7 @@ private void drawRecipeDisplay(DrawContext context, TextRenderer textRenderer, i //Draw the arrow that points to the recipe's result context.drawTextWithShadow(textRenderer, "▶", x + 96, y + 90, 0xaaffffff); + if (recipeIcon != null) context.drawItem(recipeIcon, x + 115, y + 61); } @Override @@ -191,8 +201,7 @@ public void updateSearchResults(String query) { String name = stack.getName().getString().toLowerCase(Locale.ENGLISH); List 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::toLowerCase).anyMatch(line -> line.contains(query))) { this.searchResults.add(stack); } } @@ -208,30 +217,56 @@ public void updateSearchResults(String query) { */ private void updateResultButtons() { if (this.recipeView) { - SkyblockCraftingRecipe recipe = this.recipeResults.get(this.currentPage); + SkyblockRecipe recipe = this.recipeResults.get(this.currentPage); //Clear all result buttons to make way for displaying the recipe for (SkyblockRecipeResultButton button : this.resultButtons) { button.clearDisplayStack(); } + recipeSlotButtons.clear(); //Put the recipe in the proper result buttons - //Row 1 - this.resultButtons.get(5).setDisplayStack(recipe.getGrid().getFirst()); - this.resultButtons.get(6).setDisplayStack(recipe.getGrid().get(1)); - this.resultButtons.get(7).setDisplayStack(recipe.getGrid().get(2)); - //Row 2 - this.resultButtons.get(10).setDisplayStack(recipe.getGrid().get(3)); - this.resultButtons.get(11).setDisplayStack(recipe.getGrid().get(4)); - this.resultButtons.get(12).setDisplayStack(recipe.getGrid().get(5)); - //Row 3 - this.resultButtons.get(15).setDisplayStack(recipe.getGrid().get(6)); - this.resultButtons.get(16).setDisplayStack(recipe.getGrid().get(7)); - this.resultButtons.get(17).setDisplayStack(recipe.getGrid().get(8)); - //Result - this.resultButtons.get(14).setDisplayStack(recipe.getResult()); + switch (recipe) { + case SkyblockCraftingRecipe craftingRecipe -> { + recipeIcon = new ItemStack(Items.CRAFTING_TABLE); + //Row 1 + recipeSlotButtons.add(this.resultButtons.get(5).setDisplayStack(craftingRecipe.getGrid().getFirst())); + recipeSlotButtons.add(this.resultButtons.get(6).setDisplayStack(craftingRecipe.getGrid().get(1))); + recipeSlotButtons.add(this.resultButtons.get(7).setDisplayStack(craftingRecipe.getGrid().get(2))); + //Row 2 + recipeSlotButtons.add(this.resultButtons.get(10).setDisplayStack(craftingRecipe.getGrid().get(3))); + recipeSlotButtons.add(this.resultButtons.get(11).setDisplayStack(craftingRecipe.getGrid().get(4))); + recipeSlotButtons.add(this.resultButtons.get(12).setDisplayStack(craftingRecipe.getGrid().get(5))); + //Row 3 + recipeSlotButtons.add(this.resultButtons.get(15).setDisplayStack(craftingRecipe.getGrid().get(6))); + recipeSlotButtons.add(this.resultButtons.get(16).setDisplayStack(craftingRecipe.getGrid().get(7))); + recipeSlotButtons.add(this.resultButtons.get(17).setDisplayStack(craftingRecipe.getGrid().get(8))); + //Result + recipeSlotButtons.add(this.resultButtons.get(14).setDisplayStack(craftingRecipe.getResult())); + } + case SkyblockForgeRecipe forgeRecipe -> { + + recipeIcon = new ItemStack(Items.FURNACE); + + + Vector2i gridSize = forgeRecipe.getGridSize(); + // Using this slot as a center cuz I said so + SkyblockRecipeResultButton button = this.resultButtons.get(11); + int startX = button.getX() + button.getWidth() / 2 - (gridSize.x * 25) / 2; + int startY = button.getY() + button.getHeight() / 2 - (gridSize.y * 25)/2; + for (int i = 0; i < forgeRecipe.getInputs().size(); i++) { + int x = startX + (i % gridSize.x) * 25; + int y = startY + (i / gridSize.x) * 25; + recipeSlotButtons.add(new SkyblockRecipeResultButton(x, y).setDisplayStack(forgeRecipe.getInputs().get(i))); + } + //Result + recipeSlotButtons.add(this.resultButtons.get(14).setDisplayStack(forgeRecipe.getResult())); + } + case null, default -> {} + } } else { + recipeIcon = null; //Update the result buttons with the stacks from the search results for (int i = 0; i < resultButtons.size(); ++i) { int index = this.currentPage * resultButtons.size() + i; @@ -271,7 +306,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { return true; } - for (SkyblockRecipeResultButton resultButton : this.resultButtons) { + for (SkyblockRecipeResultButton resultButton : recipeView ? recipeSlotButtons : this.resultButtons) { //If the result button was clicked then try and show a recipe if there is one //for the item if (resultButton.mouseClicked(mouseX, mouseY, button)) { @@ -280,7 +315,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { //Continue if this item doesn't have an item id if (itemId.isEmpty()) continue; - List recipes = ItemRepository.getRecipes(itemId); + List recipes = ItemRepository.getRecipesAndUsages(resultButton.getDisplayStack()); //If this item has recipes then set the fields so that they can be displayed if (!recipes.isEmpty()) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java index cc87308f87..2ac90d3860 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java @@ -30,6 +30,10 @@ public SkyblockForgeRecipe(NEUForgeRecipe forgeRecipe) { duration = forgeRecipe.getDuration(); } + public ItemStack getResult() { + return output; + } + @Override public List getInputSlots(int width, int height) { @@ -37,7 +41,7 @@ public List getInputSlots(int width, int height) { int centerX = width / 2; int centerY = height / 2; - Vector2i radius = getRadius(); + Vector2i radius = getGridSize(); int startX = (int) (centerX / 2.f - (radius.x / 2.f) * 18); int startY = (int) (centerY - (radius.y / 2.f) * 18); @@ -49,7 +53,7 @@ public List getInputSlots(int width, int height) { return out; } - private Vector2i getRadius() { + public Vector2i getGridSize() { int gridWidth; int gridHeight; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java index 0ba870c625..c3e8a8e238 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java @@ -77,12 +77,17 @@ default void render(DrawContext context, int width, int height, double mouseX, d /** * Extra text like collection requirements - * @return the text */ Text getExtraText(); + /** + * Identifier used for REI, EMI. Also used in the recipe book for the name + */ Identifier getCategoryIdentifier(); + /** + * Used for EMI. + */ Identifier getRecipeIdentifier(); record RecipeSlot(int x, int y, ItemStack stack, boolean showBackground) {