aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2020-12-20 19:59:49 +0800
committershedaniel <daniel@shedaniel.me>2020-12-20 19:59:49 +0800
commit67171a5ff24ed77e6c4cc889543e8dfb543e8fe5 (patch)
tree02909ac26d2b74ebf08f5c463f1b9a60483468df /runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
parent9784e9f7228fc0aa3ca814e3830dbd81996a3693 (diff)
downloadRoughlyEnoughItems-67171a5ff24ed77e6c4cc889543e8dfb543e8fe5.tar.gz
RoughlyEnoughItems-67171a5ff24ed77e6c4cc889543e8dfb543e8fe5.tar.bz2
RoughlyEnoughItems-67171a5ff24ed77e6c4cc889543e8dfb543e8fe5.zip
wip more
Signed-off-by: shedaniel <daniel@shedaniel.me>
Diffstat (limited to 'runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java840
1 files changed, 840 insertions, 0 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java b/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
new file mode 100644
index 000000000..3dbaf62c6
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
@@ -0,0 +1,840 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.gui;
+
+import com.google.common.collect.Lists;
+import com.mojang.blaze3d.platform.Window;
+import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.vertex.PoseStack;
+import com.mojang.blaze3d.vertex.Tesselator;
+import com.mojang.math.Matrix4f;
+import com.mojang.math.Vector4f;
+import me.shedaniel.math.Point;
+import me.shedaniel.math.Rectangle;
+import me.shedaniel.math.impl.PointHelper;
+import me.shedaniel.rei.RoughlyEnoughItemsCore;
+import me.shedaniel.rei.api.*;
+import me.shedaniel.rei.api.entry.EntryStacks;
+import me.shedaniel.rei.api.favorites.FavoriteEntry;
+import me.shedaniel.rei.api.widgets.Button;
+import me.shedaniel.rei.api.widgets.Tooltip;
+import me.shedaniel.rei.api.widgets.Widgets;
+import me.shedaniel.rei.gui.config.SearchFieldLocation;
+import me.shedaniel.rei.gui.modules.Menu;
+import me.shedaniel.rei.gui.modules.entries.GameModeMenuEntry;
+import me.shedaniel.rei.gui.modules.entries.WeatherMenuEntry;
+import me.shedaniel.rei.gui.widget.*;
+import me.shedaniel.rei.impl.*;
+import me.shedaniel.rei.utils.CollectionUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.chat.NarratorChatListener;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
+import net.minecraft.client.multiplayer.ClientLevel;
+import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.client.renderer.entity.ItemRenderer;
+import net.minecraft.client.resources.language.I18n;
+import net.minecraft.client.resources.sounds.SimpleSoundInstance;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TextComponent;
+import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.sounds.SoundEvents;
+import net.minecraft.util.FormattedCharSequence;
+import net.minecraft.world.InteractionResult;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.level.GameType;
+import net.minecraft.world.level.block.Blocks;
+import org.apache.logging.log4j.util.TriConsumer;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+@ApiStatus.Internal
+public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverlay {
+ private static final ResourceLocation CHEST_GUI_TEXTURE = new ResourceLocation("roughlyenoughitems", "textures/gui/recipecontainer.png");
+ private static final List<Tooltip> TOOLTIPS = Lists.newArrayList();
+ private static final List<Runnable> AFTER_RENDER = Lists.newArrayList();
+ private static final EntryListWidget ENTRY_LIST_WIDGET = new EntryListWidget();
+ private static FavoritesListWidget favoritesListWidget = null;
+ private final List<Widget> widgets = Lists.newLinkedList();
+ public boolean shouldReInit = false;
+ private int tooltipWidth;
+ private int tooltipHeight;
+ private List<FormattedCharSequence> tooltipLines;
+ public final TriConsumer<PoseStack, Point, Float> renderTooltipCallback = (matrices, mouse, aFloat) -> {
+ RenderSystem.disableRescaleNormal();
+ RenderSystem.disableDepthTest();
+ matrices.pushPose();
+ matrices.translate(0, 0, 999);
+ int x = mouse.x;
+ int y = mouse.y;
+ this.fillGradient(matrices, x - 3, y - 4, x + tooltipWidth + 3, y - 3, -267386864, -267386864);
+ this.fillGradient(matrices, x - 3, y + tooltipHeight + 3, x + tooltipWidth + 3, y + tooltipHeight + 4, -267386864, -267386864);
+ this.fillGradient(matrices, x - 3, y - 3, x + tooltipWidth + 3, y + tooltipHeight + 3, -267386864, -267386864);
+ this.fillGradient(matrices, x - 4, y - 3, x - 3, y + tooltipHeight + 3, -267386864, -267386864);
+ this.fillGradient(matrices, x + tooltipWidth + 3, y - 3, x + tooltipWidth + 4, y + tooltipHeight + 3, -267386864, -267386864);
+ this.fillGradient(matrices, x - 3, y - 3 + 1, x - 3 + 1, y + tooltipHeight + 3 - 1, 1347420415, 1344798847);
+ this.fillGradient(matrices, x + tooltipWidth + 2, y - 3 + 1, x + tooltipWidth + 3, y + tooltipHeight + 3 - 1, 1347420415, 1344798847);
+ this.fillGradient(matrices, x - 3, y - 3, x + tooltipWidth + 3, y - 3 + 1, 1347420415, 1347420415);
+ this.fillGradient(matrices, x - 3, y + tooltipHeight + 2, x + tooltipWidth + 3, y + tooltipHeight + 3, 1344798847, 1344798847);
+ int currentY = y;
+ MultiBufferSource.BufferSource immediate = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
+ Matrix4f matrix = matrices.last().pose();
+ for (int lineIndex = 0; lineIndex < tooltipLines.size(); lineIndex++) {
+ font.drawInBatch(tooltipLines.get(lineIndex), x, currentY, -1, true, matrix, immediate, false, 0, 15728880);
+ currentY += lineIndex == 0 ? 12 : 10;
+ }
+ immediate.endBatch();
+ matrices.popPose();
+ RenderSystem.enableDepthTest();
+ RenderSystem.enableRescaleNormal();
+ };
+ private Rectangle bounds;
+ private Window window;
+ private Button leftButton, rightButton;
+ @ApiStatus.Experimental
+ private Rectangle subsetsButtonBounds;
+
+ @Nullable
+ private ContainerScreenOverlay.OverlayMenu overlayMenu = null;
+
+ public static EntryListWidget getEntryListWidget() {
+ return ENTRY_LIST_WIDGET;
+ }
+
+ @Nullable
+ public static FavoritesListWidget getFavoritesListWidget() {
+ return favoritesListWidget;
+ }
+
+ private static class OverlayMenu {
+ @NotNull
+ private UUID uuid;
+ @NotNull
+ private Menu menu;
+ @NotNull
+ private Widget wrappedMenu;
+ @NotNull
+ private Predicate<Point> inBounds;
+
+ public OverlayMenu(@NotNull UUID uuid, @NotNull Menu menu, @NotNull Widget wrappedMenu, @NotNull Predicate<Point> inBounds) {
+ this.uuid = uuid;
+ this.menu = menu;
+ this.wrappedMenu = wrappedMenu;
+ this.inBounds = inBounds.or(point -> menu.getBounds().contains(point));
+ }
+ }
+
+ public boolean isMenuOpened(UUID uuid) {
+ return overlayMenu != null && overlayMenu.uuid.equals(uuid);
+ }
+
+ public boolean isAnyMenuOpened() {
+ return overlayMenu != null;
+ }
+
+ public boolean isMenuInBounds(UUID uuid) {
+ return isMenuOpened(uuid) && overlayMenu.inBounds.test(PointHelper.ofMouse());
+ }
+
+ private void proceedOpenMenu(UUID uuid, Runnable runnable) {
+ proceedOpenMenuOrElse(uuid, runnable, menu -> {});
+ }
+
+ private void proceedOpenMenuOrElse(UUID uuid, Runnable runnable, Consumer<OverlayMenu> orElse) {
+ if (overlayMenu == null || !overlayMenu.uuid.equals(uuid)) {
+ removeOverlayMenu();
+ runnable.run();
+ } else {
+ orElse.accept(this.overlayMenu);
+ }
+ }
+
+ public void openMenu(UUID uuid, Menu menu, Predicate<Point> inPoint) {
+ this.overlayMenu = new OverlayMenu(uuid, menu, InternalWidgets.wrapTranslate(menu, 0, 0, 400), inPoint);
+ }
+
+ @ApiStatus.Internal
+ @Nullable
+ public Menu getSubsetsMenu() {
+ if (isMenuOpened(Menu.SUBSETS))
+ return this.overlayMenu.menu;
+ throw new IllegalStateException("Subsets menu accessed when subsets are not opened!");
+ }
+
+ @ApiStatus.Internal
+ public void removeOverlayMenu() {
+ OverlayMenu tmpOverlayMenu = this.overlayMenu;
+ if (tmpOverlayMenu != null)
+ AFTER_RENDER.add(() -> this.widgets.remove(tmpOverlayMenu.wrappedMenu));
+ this.overlayMenu = null;
+ }
+
+ @Override
+ public void queueReloadOverlay() {
+ shouldReInit = true;
+ }
+
+ public void init(boolean useless) {
+ init();
+ }
+
+ public void init() {
+ this.shouldReInit = false;
+ //Update Variables
+ this.children().clear();
+ this.removeOverlayMenu();
+ this.window = Minecraft.getInstance().getWindow();
+ this.bounds = DisplayHelper.getInstance().getOverlayBounds(ConfigObject.getInstance().getDisplayPanelLocation(), Minecraft.getInstance().screen);
+ widgets.add(ENTRY_LIST_WIDGET);
+ if (ConfigObject.getInstance().isFavoritesEnabled()) {
+ if (favoritesListWidget == null)
+ favoritesListWidget = new FavoritesListWidget();
+// favoritesListWidget.favoritePanel.resetRows();
+ widgets.add(favoritesListWidget);
+ }
+ ENTRY_LIST_WIDGET.updateArea(ScreenHelper.getSearchField() == null ? "" : ScreenHelper.getSearchField().getText());
+ if (ScreenHelper.getSearchField() == null) {
+ ScreenHelper.setSearchField(new OverlaySearchField(0, 0, 0, 0));
+ }
+ ScreenHelper.getSearchField().getBounds().setBounds(getSearchFieldArea());
+ this.widgets.add(ScreenHelper.getSearchField());
+ ScreenHelper.getSearchField().setChangedListener(s -> ENTRY_LIST_WIDGET.updateSearch(s, false));
+ if (!ConfigObject.getInstance().isEntryListWidgetScrolled()) {
+ widgets.add(leftButton = Widgets.createButton(new Rectangle(bounds.x, bounds.y + (ConfigObject.getInstance().getSearchFieldLocation() == SearchFieldLocation.TOP_SIDE ? 24 : 0) + 5, 16, 16), new TranslatableComponent("text.rei.left_arrow"))
+ .onClick(button -> {
+ ENTRY_LIST_WIDGET.previousPage();
+ if (ENTRY_LIST_WIDGET.getPage() < 0)
+ ENTRY_LIST_WIDGET.setPage(ENTRY_LIST_WIDGET.getTotalPages() - 1);
+ ENTRY_LIST_WIDGET.updateEntriesPosition();
+ })
+ .containsMousePredicate((button, point) -> button.getBounds().contains(point) && isNotInExclusionZones(point.x, point.y))
+ .tooltipLine(I18n.get("text.rei.previous_page"))
+ .focusable(false));
+ widgets.add(rightButton = Widgets.createButton(new Rectangle(bounds.x + bounds.width - 18, bounds.y + (ConfigObject.getInstance().getSearchFieldLocation() == SearchFieldLocation.TOP_SIDE ? 24 : 0) + 5, 16, 16), new TranslatableComponent("text.rei.right_arrow"))
+ .onClick(button -> {
+ ENTRY_LIST_WIDGET.nextPage();
+ if (ENTRY_LIST_WIDGET.getPage() >= ENTRY_LIST_WIDGET.getTotalPages())
+ ENTRY_LIST_WIDGET.setPage(0);
+ ENTRY_LIST_WIDGET.updateEntriesPosition();
+ })
+ .containsMousePredicate((button, point) -> button.getBounds().contains(point) && isNotInExclusionZones(point.x, point.y))
+ .tooltipLine(I18n.get("text.rei.next_page"))
+ .focusable(false));
+ }
+
+ final Rectangle configButtonArea = getConfigButtonArea();
+ Widget tmp;
+ widgets.add(tmp = InternalWidgets.wrapLateRenderable(InternalWidgets.mergeWidgets(
+ Widgets.createButton(configButtonArea, NarratorChatListener.NO_TITLE)
+ .onClick(button -> {
+ if (Screen.hasShiftDown() || Screen.hasControlDown()) {
+ ClientHelper.getInstance().setCheating(!ClientHelper.getInstance().isCheating());
+ return;
+ }
+ ConfigManager.getInstance().openConfigScreen(REIHelper.getInstance().getPreviousContainerScreen());
+ })
+ .onRender((matrices, button) -> {
+ if (ClientHelper.getInstance().isCheating() && RoughlyEnoughItemsCore.hasOperatorPermission()) {
+ button.setTint(RoughlyEnoughItemsCore.hasPermissionToUsePackets() ? 721354752 : 1476440063);
+ } else {
+ button.removeTint();
+ }
+ })
+ .focusable(false)
+ .containsMousePredicate((button, point) -> button.getBounds().contains(point) && isNotInExclusionZones(point.x, point.y))
+ .tooltipSupplier(button -> {
+ String tooltips = I18n.get("text.rei.config_tooltip");
+ tooltips += "\n ";
+ if (!ClientHelper.getInstance().isCheating())
+ tooltips += "\n" + I18n.get("text.rei.cheating_disabled");
+ else if (!RoughlyEnoughItemsCore.hasOperatorPermission()) {
+ if (minecraft.gameMode.hasInfiniteItems())
+ tooltips += "\n" + I18n.get("text.rei.cheating_limited_creative_enabled");
+ else tooltips += "\n" + I18n.get("text.rei.cheating_enabled_no_perms");
+ } else if (RoughlyEnoughItemsCore.hasPermissionToUsePackets())
+ tooltips += "\n" + I18n.get("text.rei.cheating_enabled");
+ else
+ tooltips += "\n" + I18n.get("text.rei.cheating_limited_enabled");
+ return tooltips;
+ }),
+ Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
+ helper.setBlitOffset(helper.getBlitOffset() + 1);
+ Minecraft.getInstance().getTextureManager().bind(CHEST_GUI_TEXTURE);
+ helper.blit(matrices, configButtonArea.x + 3, configButtonArea.y + 3, 0, 0, 14, 14);
+ })
+ )
+ ));
+ tmp.setZ(600);
+ if (ConfigObject.getInstance().doesShowUtilsButtons()) {
+ widgets.add(Widgets.createButton(ConfigObject.getInstance().isLowerConfigButton() ? new Rectangle(ConfigObject.getInstance().isLeftHandSidePanel() ? window.getGuiScaledWidth() - 30 : 10, 10, 20, 20) : new Rectangle(ConfigObject.getInstance().isLeftHandSidePanel() ? window.getGuiScaledWidth() - 55 : 35, 10, 20, 20), NarratorChatListener.NO_TITLE)
+ .onRender((matrices, button) -> {
+ boolean isOpened = isMenuOpened(Menu.GAME_TYPE);
+ if (isOpened || !isAnyMenuOpened()) {
+ boolean inBounds = (button.isFocused() || button.containsMouse(PointHelper.ofMouse())) || isMenuInBounds(Menu.GAME_TYPE);
+ if (isOpened != inBounds) {
+ if (inBounds) {
+ Menu menu = new Menu(new Point(button.getBounds().x, button.getBounds().getMaxY()),
+ CollectionUtils.map(GameType.values(), GameModeMenuEntry::new));
+ if (ConfigObject.getInstance().isLeftHandSidePanel())
+ menu.menuStartPoint.x -= menu.getBounds().width - button.getBounds().width;
+ openMenu(Menu.GAME_TYPE, menu, point -> button.isFocused() && button.containsMouse(PointHelper.ofMouse()));
+ } else {
+ removeOverlayMenu();
+ }
+ }
+ }
+ button.setText(new TextComponent(getGameModeShortText(getCurrentGameMode())));
+ })
+ .focusable(false)
+ .tooltipLine(I18n.get("text.rei.gamemode_button.tooltip.all"))
+ .containsMousePredicate((button, point) -> button.getBounds().contains(point) && isNotInExclusionZones(point.x, point.y)));
+ Button weatherButton;
+ widgets.add(weatherButton = Widgets.createButton(new Rectangle(ConfigObject.getInstance().isLeftHandSidePanel() ? window.getGuiScaledWidth() - 30 : 10, 35, 20, 20), NarratorChatListener.NO_TITLE)
+ .onRender((matrices, button) -> {
+ boolean isOpened = isMenuOpened(Menu.WEATHER);
+ if (isOpened || !isAnyMenuOpened()) {
+ boolean inBounds = (button.isFocused() || button.containsMouse(PointHelper.ofMouse())) || isMenuInBounds(Menu.WEATHER);
+ if (isOpened != inBounds) {
+ if (inBounds) {
+ Menu menu = new Menu(new Point(button.getBounds().x, button.getBounds().getMaxY()),
+ CollectionUtils.map(Weather.values(), WeatherMenuEntry::new));
+ if (ConfigObject.getInstance().isLeftHandSidePanel())
+ menu.menuStartPoint.x -= menu.getBounds().width - button.getBounds().width;
+ openMenu(Menu.WEATHER, menu, point -> button.isFocused() && button.containsMouse(PointHelper.ofMouse()));
+ } else {
+ removeOverlayMenu();
+ }
+ }
+ }
+ })
+ .tooltipLine(I18n.get("text.rei.weather_button.tooltip.all"))
+ .focusable(false)
+ .containsMousePredicate((button, point) -> button.getBounds().contains(point) && isNotInExclusionZones(point.x, point.y)));
+ widgets.add(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
+ Minecraft.getInstance().getTextureManager().bind(CHEST_GUI_TEXTURE);
+ RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
+ helper.blit(matrices, weatherButton.getBounds().x + 3, weatherButton.getBounds().y + 3, getCurrentWeather().getId() * 14, 14, 14, 14);
+ }));
+ }
+ subsetsButtonBounds = getSubsetsButtonBounds();
+ if (ConfigObject.getInstance().isSubsetsEnabled()) {
+ widgets.add(InternalWidgets.wrapLateRenderable(InternalWidgets.wrapTranslate(Widgets.createButton(subsetsButtonBounds, ClientHelperImpl.getInstance().isAprilFools.get() ? new TranslatableComponent("text.rei.tiny_potato") : new TranslatableComponent("text.rei.subsets"))
+ .onClick(button -> {
+ proceedOpenMenuOrElse(Menu.SUBSETS, () -> {
+ openMenu(Menu.SUBSETS, Menu.createSubsetsMenuFromRegistry(new Point(this.subsetsButtonBounds.x, this.subsetsButtonBounds.getMaxY())), point -> true);
+ }, menu -> {
+ removeOverlayMenu();
+ });
+ }), 0, 0, 600)));
+ }
+ if (!ConfigObject.getInstance().isEntryListWidgetScrolled()) {
+ widgets.add(Widgets.createClickableLabel(new Point(bounds.x + (bounds.width / 2), bounds.y + (ConfigObject.getInstance().getSearchFieldLocation() == SearchFieldLocation.TOP_SIDE ? 24 : 0) + 10), NarratorChatListener.NO_TITLE, label -> {
+ ENTRY_LIST_WIDGET.setPage(0);
+ ENTRY_LIST_WIDGET.updateEntriesPosition();
+ }).tooltipLine(I18n.get("text.rei.go_back_first_page")).focusable(false).onRender((matrices, label) -> {
+ label.setClickable(ENTRY_LIST_WIDGET.getTotalPages() > 1);
+ label.setText(new TextComponent(String.format("%s/%s", ENTRY_LIST_WIDGET.getPage() + 1, Math.max(ENTRY_LIST_WIDGET.getTotalPages(), 1))));
+ }).rainbow(new Random().nextFloat() < 1.0E-4D || ClientHelperImpl.getInstance().isAprilFools.get()));
+ }
+ if (ConfigObject.getInstance().isCraftableFilterEnabled()) {
+ Rectangle area = getCraftableToggleArea();
+ ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
+ ItemStack icon = new ItemStack(Blocks.CRAFTING_TABLE);
+ this.widgets.add(tmp = InternalWidgets.wrapLateRenderable(InternalWidgets.mergeWidgets(
+ Widgets.createButton(area, NarratorChatListener.NO_TITLE)
+ .focusable(false)
+ .onClick(button -> {
+ ConfigManager.getInstance().toggleCraftableOnly();
+ ENTRY_LIST_WIDGET.updateSearch(ScreenHelper.getSearchField().getText(), true);
+ })
+ .onRender((matrices, button) -> button.setTint(ConfigManager.getInstance().isCraftableOnlyEnabled() ? 939579655 : 956235776))
+ .containsMousePredicate((button, point) -> button.getBounds().contains(point) && isNotInExclusionZones(point.x, point.y))
+ .tooltipSupplier(button -> I18n.get(ConfigManager.getInstance().isCraftableOnlyEnabled() ? "text.rei.showing_craftable" : "text.rei.showing_all")),
+ Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
+ Vector4f vector = new Vector4f(area.x + 2, area.y + 2, helper.getBlitOffset() - 10, 1.0F);
+ vector.transform(matrices.last().pose());
+ itemRenderer.blitOffset = vector.z();
+ itemRenderer.renderGuiItem(icon, (int) vector.x(), (int) vector.y());
+ itemRenderer.blitOffset = 0.0F;
+ }))
+ ));
+ tmp.setZ(600);
+ }
+ }
+
+ private Rectangle getSubsetsButtonBounds() {
+ if (ConfigObject.getInstance().isSubsetsEnabled()) {
+ if (Minecraft.getInstance().screen instanceof RecipeViewingScreen) {
+ RecipeViewingScreen widget = (RecipeViewingScreen) Minecraft.getInstance().screen;
+ return new Rectangle(widget.getBounds().x, 3, widget.getBounds().width, 18);
+ }
+ if (Minecraft.getInstance().screen instanceof VillagerRecipeViewingScreen) {
+ VillagerRecipeViewingScreen widget = (VillagerRecipeViewingScreen) Minecraft.getInstance().screen;
+ return new Rectangle(widget.bounds.x, 3, widget.bounds.width, 18);
+ }
+ AbstractContainerScreen<?> containerScreen = REIHelper.getInstance().getPreviousContainerScreen();
+ if (containerScreen != null)
+ return new Rectangle(containerScreen.leftPos, 3, containerScreen.imageWidth, 18);
+ }
+ return null;
+ }
+
+ private Weather getNextWeather() {
+ try {
+ Weather current = getCurrentWeather();
+ int next = current.getId() + 1;
+ if (next >= 3)
+ next = 0;
+ return Weather.byId(next);
+ } catch (Exception e) {
+ return Weather.CLEAR;
+ }
+ }
+
+ private Weather getCurrentWeather() {
+ ClientLevel world = Minecraft.getInstance().level;
+ if (world.isThundering())
+ return Weather.THUNDER;
+ if (world.getLevelData().isRaining())
+ return Weather.RAIN;
+ return Weather.CLEAR;
+ }
+
+ private String getGameModeShortText(GameType gameMode) {
+ return I18n.get("text.rei.short_gamemode." + gameMode.getName());
+ }
+
+ private String getGameModeText(GameType gameMode) {
+ return I18n.get("selectWorld.gameMode." + gameMode.getName());
+ }
+
+ private GameType getCurrentGameMode() {
+ return Minecraft.getInstance().getConnection().getPlayerInfo(Minecraft.getInstance().player.getGameProfile().getId()).getGameMode();
+ }
+
+ private Rectangle getSearchFieldArea() {
+ int widthRemoved = 1;
+ if (ConfigObject.getInstance().isCraftableFilterEnabled()) widthRemoved += 22;
+ if (ConfigObject.getInstance().isLowerConfigButton()) widthRemoved += 22;
+ SearchFieldLocation searchFieldLocation = ScreenHelper.getContextualSearchFieldLocation();
+ switch (searchFieldLocation) {
+ case TOP_SIDE:
+ return getTopSideSearchFieldArea(widthRemoved);
+ case BOTTOM_SIDE:
+ return getBottomSideSearchFieldArea(widthRemoved);
+ default:
+ case CENTER: {
+ for (OverlayDecider decider : DisplayHelper.getInstance().getSortedOverlayDeciders(Minecraft.getInstance().screen.getClass())) {
+ if (decider instanceof DisplayHelper.DisplayBoundsProvider) {
+ Rectangle containerBounds = ((DisplayHelper.DisplayBoundsProvider<Screen>) decider).getScreenBounds(Minecraft.getInstance().screen);
+ return getBottomCenterSearchFieldArea(containerBounds, widthRemoved);
+ }
+ }
+ return new Rectangle();
+ }
+ }
+ }
+
+ private Rectangle getTopSideSearchFieldArea(int widthRemoved) {
+ return new Rectangle(bounds.x + 2, 4, bounds.width - 6 - widthRemoved, 18);
+ }
+
+ private Rectangle getBottomSideSearchFieldArea(int widthRemoved) {
+ return new Rectangle(bounds.x + 2, window.getGuiScaledHeight() - 22, bounds.width - 6 - widthRemoved, 18);
+ }
+
+ private Rectangle getBottomCenterSearchFieldArea(Rectangle containerBounds, int widthRemoved) {
+ return new Rectangle(containerBounds.x, window.getGuiScaledHeight() - 22, containerBounds.width - widthRemoved, 18);
+ }
+
+ private Rectangle getCraftableToggleArea() {
+ Rectangle area = getSearchFieldArea();
+ area.setLocation(area.x + area.width + 4, area.y - 1);
+ area.setSize(20, 20);
+ return area;
+ }
+
+ private Rectangle getConfigButtonArea() {
+ if (ConfigObject.getInstance().isLowerConfigButton()) {
+ Rectangle area = getSearchFieldArea();
+ area.setLocation(area.x + area.width + (ConfigObject.getInstance().isCraftableFilterEnabled() ? 26 : 4), area.y - 1);
+ area.setSize(20, 20);
+ return area;
+ }
+ return new Rectangle(ConfigObject.getInstance().isLeftHandSidePanel() ? window.getGuiScaledWidth() - 30 : 10, 10, 20, 20);
+ }
+
+ private String getCheatModeText() {
+ return I18n.get(String.format("%s%s", "text.rei.", ClientHelper.getInstance().isCheating() ? "cheat" : "nocheat"));
+ }
+
+ @NotNull
+ @Override
+ public Rectangle getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public void render(PoseStack matrices, int mouseX, int mouseY, float delta) {
+ if (shouldReInit) {
+ ENTRY_LIST_WIDGET.updateSearch(ScreenHelper.getSearchField().getText(), true);
+ init();
+ } else {
+ for (OverlayDecider decider : DisplayHelper.getInstance().getSortedOverlayDeciders(minecraft.screen.getClass())) {
+ if (decider != null && decider.shouldRecalculateArea(ConfigObject.getInstance().getDisplayPanelLocation(), bounds)) {
+ init();
+ break;
+ }
+ }
+ }
+ if (ConfigManager.getInstance().isCraftableOnlyEnabled()) {
+ Set<EntryStack<?>> currentStacks = ClientHelperImpl.getInstance()._getInventoryItemsTypes();
+ if (!currentStacks.equals(ScreenHelper.inventoryStacks)) {
+ ScreenHelper.inventoryStacks = currentStacks;
+ ENTRY_LIST_WIDGET.updateSearch(ScreenHelper.getSearchField().getText(), true);
+ }
+ }
+ if (OverlaySearchField.isHighlighting) {
+ matrices.pushPose();
+ matrices.translate(0, 0, 200f);
+ if (Minecraft.getInstance().screen instanceof AbstractContainerScreen) {
+ AbstractContainerScreen<?> containerScreen = (AbstractContainerScreen<?>) Minecraft.getInstance().screen;
+ int x = containerScreen.leftPos, y = containerScreen.topPos;
+ for (Slot slot : containerScreen.getMenu().slots)
+ if (!slot.hasItem() || !ENTRY_LIST_WIDGET.canLastSearchTermsBeAppliedTo(EntryStacks.of(slot.getItem())))
+ fillGradient(matrices, x + slot.x, y + slot.y, x + slot.x + 16, y + slot.y + 16, -601874400, -601874400);
+ }
+ matrices.popPose();
+ }
+ RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
+ this.renderWidgets(matrices, mouseX, mouseY, delta);
+ if (ConfigObject.getInstance().areClickableRecipeArrowsEnabled()) {
+ List<ResourceLocation> categories = null;
+ Screen screen = Minecraft.getInstance().screen;
+ ClickAreaHandler.ClickAreaContext context = new ClickAreaHandler.ClickAreaContext<Screen>() {
+ @Override
+ public Screen getScreen() {
+ return screen;
+ }
+
+ @Override
+ public Point getMousePosition() {
+ return new Point(mouseX, mouseY);
+ }
+ };
+ for (Map.Entry<Class<? extends Screen>, ClickAreaHandler<?>> area : ((RecipeHelperImpl) RecipeHelper.getInstance()).getClickAreas().entries()) {
+ if (area.getKey().equals(screen.getClass())) {
+ ClickAreaHandler.Result result = area.getValue().handle(context);
+ if (result.isSuccessful()) {
+ if (categories == null) {
+ categories = result.getCategories().collect(Collectors.toList());
+ } else categories.addAll(result.getCategories().collect(Collectors.toList()));
+ }
+ }
+ }
+ if (categories != null && !categories.isEmpty()) {
+ String collect = CollectionUtils.mapAndJoinToString(categories, identifier -> RecipeHelper.getInstance().getCategory(identifier).getCategoryName(), ", ");
+ Tooltip.create(new TranslatableComponent("text.rei.view_recipes_for", collect)).queue();
+ }
+ }
+ }
+
+ public void lateRender(PoseStack matrices, int mouseX, int mouseY, float delta) {
+ if (ScreenHelper.isOverlayVisible()) {
+ ScreenHelper.getSearchField().laterRender(matrices, mouseX, mouseY, delta);
+ for (Widget widget : widgets) {
+ if (widget instanceof LateRenderable && (overlayMenu == null || overlayMenu.wrappedMenu != widget))
+ widget.render(matrices, mouseX, mouseY, delta);
+ }
+ }
+ if (overlayMenu != null) {
+ if (overlayMenu.wrappedMenu.containsMouse(mouseX, mouseY)) {
+ TOOLTIPS.clear();
+ }
+ overlayMenu.wrappedMenu.render(matrices, mouseX, mouseY, delta);
+ }
+ Screen currentScreen = Minecraft.getInstance().screen;
+ if (!(currentScreen instanceof RecipeViewingScreen) || !((RecipeViewingScreen) currentScreen).choosePageActivated)
+ for (Tooltip tooltip : TOOLTIPS) {
+ if (tooltip != null)
+ renderTooltip(matrices, tooltip);
+ }
+ for (Runnable runnable : AFTER_RENDER) {
+ runnable.run();
+ }
+ TOOLTIPS.clear();
+ AFTER_RENDER.clear();
+ }
+
+ public void renderTooltip(PoseStack matrices, Tooltip tooltip) {
+ renderTooltip(matrices, tooltip.getText(), tooltip.getX(), tooltip.getY());
+ }
+
+ public void renderTooltip(PoseStack matrices, List<Component> lines, int mouseX, int mouseY) {
+ if (lines.isEmpty())
+ return;
+ List<FormattedCharSequence> orderedTexts = CollectionUtils.map(lines, Component::getVisualOrderText);
+ renderTooltipInner(matrices, orderedTexts, mouseX, mouseY);
+ }
+
+ public void renderTooltipInner(PoseStack matrices, List<FormattedCharSequence> lines, int mouseX, int mouseY) {
+ if (lines.isEmpty())
+ return;
+ matrices.pushPose();
+ matrices.translate(0, 0, 500);
+ minecraft.screen.renderTooltip(matrices, lines, mouseX, mouseY);
+ matrices.popPose();
+ }
+
+ public void addTooltip(@Nullable Tooltip tooltip) {
+ if (tooltip != null)
+ TOOLTIPS.add(tooltip);
+ }
+
+ public void renderWidgets(PoseStack matrices, int mouseX, int mouseY, float delta) {
+ if (!ScreenHelper.isOverlayVisible())
+ return;
+ if (!ConfigObject.getInstance().isEntryListWidgetScrolled()) {
+ leftButton.setEnabled(ENTRY_LIST_WIDGET.getTotalPages() > 1);
+ rightButton.setEnabled(ENTRY_LIST_WIDGET.getTotalPages() > 1);
+ }
+ for (Widget widget : widgets) {
+ if (!(widget instanceof LateRenderable))
+ widget.render(matrices, mouseX, mouseY, delta);
+ }
+ }
+
+ @Override
+ public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
+ if (!ScreenHelper.isOverlayVisible())
+ return false;
+ if (overlayMenu != null && overlayMenu.wrappedMenu.mouseScrolled(mouseX, mouseY, amount))
+ return true;
+ if (isInside(PointHelper.ofMouse())) {
+ if (ENTRY_LIST_WIDGET.mouseScrolled(mouseX, mouseY, amount)) {
+ return true;
+ }
+ if (!Screen.hasControlDown() && !ConfigObject.getInstance().isEntryListWidgetScrolled()) {
+ if (amount > 0 && leftButton.isEnabled())
+ leftButton.onClick();
+ else if (amount < 0 && rightButton.isEnabled())
+ rightButton.onClick();
+ else
+ return false;
+ return true;
+ }
+ }
+ if (isNotInExclusionZones(PointHelper.getMouseX(), PointHelper.getMouseY())) {
+ if (favoritesListWidget != null && favoritesListWidget.mouseScrolled(mouseX, mouseY, amount))
+ return true;
+ }
+ for (Widget widget : widgets)
+ if (widget != ENTRY_LIST_WIDGET && (favoritesListWidget == null || widget != favoritesListWidget)
+ && (overlayMenu == null || widget != overlayMenu.wrappedMenu)
+ && widget.mouseScrolled(mouseX, mouseY, amount))
+ return true;
+ return false;
+ }
+
+ @Override
+ public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
+ if (ScreenHelper.isOverlayVisible()) {
+ if (ScreenHelper.getSearchField().keyPressed(keyCode, scanCode, modifiers))
+ return true;
+ for (GuiEventListener listener : widgets)
+ if (listener != ScreenHelper.getSearchField() && listener.keyPressed(keyCode, scanCode, modifiers))
+ return true;
+ }
+ if (ConfigObject.getInstance().getHideKeybind().matchesKey(keyCode, scanCode)) {
+ ScreenHelper.toggleOverlayVisible();
+ return true;
+ }
+ EntryStack<?> stack = RecipeHelper.getInstance().getScreenFocusedStack(Minecraft.getInstance().screen);
+ if (stack != null && !stack.isEmpty()) {
+ stack = stack.copy();
+ if (ConfigObject.getInstance().getRecipeKeybind().matchesKey(keyCode, scanCode)) {
+ return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addRecipesFor(stack).setOutputNotice(stack).fillPreferredOpenedCategory());
+ } else if (ConfigObject.getInstance().getUsageKeybind().matchesKey(keyCode, scanCode)) {
+ return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addUsagesFor(stack).setInputNotice(stack).fillPreferredOpenedCategory());
+ } else if (ConfigObject.getInstance().getFavoriteKeyCode().matchesKey(keyCode, scanCode)) {
+ FavoriteEntry favoriteEntry = FavoriteEntry.fromEntryStack(stack);
+ if (!ConfigObject.getInstance().getFavoriteEntries().contains(favoriteEntry))
+ ConfigObject.getInstance().getFavoriteEntries().add(favoriteEntry);
+ ConfigManager.getInstance().saveConfig();
+ FavoritesListWidget favoritesListWidget = ContainerScreenOverlay.getFavoritesListWidget();
+ if (favoritesListWidget != null)
+ favoritesListWidget.updateSearch(ContainerScreenOverlay.getEntryListWidget(), ScreenHelper.getSearch