diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/AlternativesScreen.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/AlternativesScreen.java index 70c7b735a..7661de56f 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/AlternativesScreen.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/AlternativesScreen.java @@ -1,6 +1,7 @@ package com.refinedmods.refinedstorage.common.autocrafting; import com.refinedmods.refinedstorage.common.Platform; +import com.refinedmods.refinedstorage.common.support.ResourceSlotRendering; import com.refinedmods.refinedstorage.common.support.TextureIds; import com.refinedmods.refinedstorage.common.support.amount.AbstractAmountScreen; import com.refinedmods.refinedstorage.common.support.amount.AmountScreenConfiguration; @@ -273,7 +274,7 @@ private static int getOverflowRows(final Alternative alternative) { @Override protected void renderResourceSlots(final GuiGraphics graphics) { - tryRenderResourceSlot(graphics, getMenu().getAmountSlot()); + ResourceSlotRendering.render(graphics, getMenu().getAmountSlot(), leftPos, topPos); } @Override @@ -416,7 +417,7 @@ private void renderSlots(final List slots, final int mouseY) { for (final ResourceSlot resourceSlot : slots) { if (resourceSlot.isActive()) { - tryRenderResourceSlot(graphics, resourceSlot); + ResourceSlotRendering.render(graphics, resourceSlot, leftPos, topPos); if (isHovering(resourceSlot.x, resourceSlot.y, 16, 16, mouseX, mouseY) && canInteractWithResourceSlot(resourceSlot, mouseX, mouseY)) { renderSlotHighlight(graphics, leftPos + resourceSlot.x, topPos + resourceSlot.y, 0); diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/CraftingPatternGridRenderer.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/CraftingPatternGridRenderer.java new file mode 100644 index 000000000..cd6c530cc --- /dev/null +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/CraftingPatternGridRenderer.java @@ -0,0 +1,104 @@ +package com.refinedmods.refinedstorage.common.autocrafting; + +import com.refinedmods.refinedstorage.common.support.widget.CustomCheckboxWidget; + +import java.util.function.Consumer; +import javax.annotation.Nullable; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; + +import static com.refinedmods.refinedstorage.common.autocrafting.PatternGridScreen.INSET_PADDING; +import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createIdentifier; +import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createTranslation; + +class CraftingPatternGridRenderer implements PatternGridRenderer { + private static final ResourceLocation CRAFTING = createIdentifier("pattern_grid/crafting"); + private static final MutableComponent FUZZY_MODE = createTranslation("gui", "pattern_grid.fuzzy_mode"); + private static final MutableComponent FUZZY_MODE_ON_HELP = + createTranslation("gui", "pattern_grid.fuzzy_mode.on.help"); + private static final MutableComponent FUZZY_MODE_OFF_HELP = + createTranslation("gui", "pattern_grid.fuzzy_mode.off.help"); + + @Nullable + private CustomCheckboxWidget fuzzyModeCheckbox; + + private final PatternGridContainerMenu menu; + private final int leftPos; + private final int x; + private final int y; + + CraftingPatternGridRenderer(final PatternGridContainerMenu menu, final int leftPos, final int x, final int y) { + this.menu = menu; + this.leftPos = leftPos; + this.x = x; + this.y = y; + } + + @Override + public void addWidgets(final Consumer widgets, final Consumer renderables) { + this.fuzzyModeCheckbox = createFuzzyModeCheckbox(); + renderables.accept(fuzzyModeCheckbox); + } + + private CustomCheckboxWidget createFuzzyModeCheckbox() { + final CustomCheckboxWidget checkbox = new CustomCheckboxWidget( + x + INSET_PADDING, + y + INSET_PADDING + 54 + INSET_PADDING - 2, + FUZZY_MODE, + Minecraft.getInstance().font, + menu.isFuzzyMode(), + CustomCheckboxWidget.Size.SMALL + ); + checkbox.setOnPressed((c, selected) -> menu.setFuzzyMode(selected)); + checkbox.setTooltip(getFuzzyModeTooltip(menu.isFuzzyMode())); + checkbox.visible = isFuzzyModeCheckboxVisible(); + return checkbox; + } + + private static Tooltip getFuzzyModeTooltip(final boolean fuzzyMode) { + return fuzzyMode ? Tooltip.create(FUZZY_MODE_ON_HELP) : Tooltip.create(FUZZY_MODE_OFF_HELP); + } + + @Override + public int getClearButtonX() { + return leftPos + 68; + } + + @Override + public int getClearButtonY() { + return y + INSET_PADDING; + } + + @Override + public void patternTypeChanged(final PatternType newPatternType) { + if (fuzzyModeCheckbox != null) { + fuzzyModeCheckbox.visible = isFuzzyModeCheckboxVisible(); + } + } + + private boolean isFuzzyModeCheckboxVisible() { + return menu.getPatternType() == PatternType.CRAFTING; + } + + @Override + public void fuzzyModeChanged(final boolean newFuzzyMode) { + if (fuzzyModeCheckbox == null) { + return; + } + fuzzyModeCheckbox.setSelected(newFuzzyMode); + fuzzyModeCheckbox.setTooltip(getFuzzyModeTooltip(newFuzzyMode)); + } + + @Override + public void renderBackground(final GuiGraphics graphics, + final float partialTicks, + final int mouseX, + final int mouseY) { + graphics.blitSprite(CRAFTING, x + INSET_PADDING, y + INSET_PADDING, 130, 54); + } +} diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridContainerMenu.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridContainerMenu.java index 67c427475..13c7a0dbe 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridContainerMenu.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridContainerMenu.java @@ -41,6 +41,8 @@ public class PatternGridContainerMenu extends AbstractGridContainerMenu { private static final int SPACING_BETWEEN_PATTERN_INPUT_AND_PATTERN_OUTPUT_SLOTS = 36; private static final int Y_OFFSET_BETWEEN_PLAYER_INVENTORY_AND_FIRST_CRAFTING_MATRIX_SLOT = 85; private static final int Y_OFFSET_BETWEEN_PLAYER_INVENTORY_AND_FIRST_PROCESSING_MATRIX_SLOT = 76; + private static final int Y_OFFSET_BETWEEN_PLAYER_INVENTORY_AND_STONECUTTER_SLOT = 63; + private static final int Y_OFFSET_BETWEEN_PLAYER_INVENTORY_AND_SMITHING_TABLE_SLOTS = 63; private static final int INDIVIDUAL_PROCESSING_MATRIX_SIZE = 54; private final RateLimiter allowedAlternativesCacheCheckerRateLimiter = RateLimiter.create(2); @@ -296,7 +298,8 @@ private void addProcessingMatrixSlots(final int x, } private void addStonecutterSlots(final int playerInventoryY) { - addSlot(new FilterSlot(stonecutterInput, 0, 17, playerInventoryY - 63) { + final int slotY = playerInventoryY - Y_OFFSET_BETWEEN_PLAYER_INVENTORY_AND_STONECUTTER_SLOT; + addSlot(new FilterSlot(stonecutterInput, 0, 13, slotY) { @Override public boolean isActive() { return getPatternType() == PatternType.STONECUTTER; @@ -305,9 +308,10 @@ public boolean isActive() { } private void addSmithingTableSlots(final int playerInventoryY) { + final int y = playerInventoryY - Y_OFFSET_BETWEEN_PLAYER_INVENTORY_AND_SMITHING_TABLE_SLOTS; for (int i = 0; i < 3; ++i) { final int ii = i; - addSlot(new FilterSlot(smithingTableMatrix, i, 13 + (i * 18), playerInventoryY - 63) { + addSlot(new FilterSlot(smithingTableMatrix, i, 13 + (i * 18), y) { @Override public boolean isActive() { return getPatternType() == PatternType.SMITHING_TABLE; @@ -324,7 +328,7 @@ public boolean mayPlace(final ItemStack stack) { } }); } - addSlot(new DisabledSlot(smithingTableResult, 0, 93, playerInventoryY - 63) { + addSlot(new DisabledSlot(smithingTableResult, 0, 93, y) { @Override public boolean isActive() { return getPatternType() == PatternType.SMITHING_TABLE; @@ -408,8 +412,8 @@ Set getAllowedAlternatives(final int containerSlot) { } interface PatternGridListener { - void patternTypeChanged(PatternType value); + void patternTypeChanged(PatternType newPatternType); - void fuzzyModeChanged(boolean value); + void fuzzyModeChanged(boolean newFuzzyMode); } } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridRenderer.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridRenderer.java new file mode 100644 index 000000000..e8222e533 --- /dev/null +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridRenderer.java @@ -0,0 +1,77 @@ +package com.refinedmods.refinedstorage.common.autocrafting; + +import com.refinedmods.refinedstorage.common.support.containermenu.ResourceSlot; + +import java.util.function.Consumer; +import javax.annotation.Nullable; + +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.world.inventory.Slot; + +interface PatternGridRenderer { + default void addWidgets(Consumer widgets, + Consumer renderables) { + // no op + } + + default void tick() { + // no op + } + + default void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + // no op + } + + int getClearButtonX(); + + int getClearButtonY(); + + void renderBackground(GuiGraphics graphics, + float partialTicks, + int mouseX, + int mouseY); + + default void renderTooltip(Font font, + @Nullable Slot hoveredSlot, + GuiGraphics graphics, + int mouseX, + int mouseY) { + // no op + } + + default void renderLabels(GuiGraphics graphics, Font font, int mouseX, int mouseY) { + // no op + } + + default boolean mouseClicked(double mouseX, double mouseY, int clickedButton) { + return false; + } + + default void mouseMoved(double mouseX, double mouseY) { + // no op + } + + default boolean mouseReleased(double mouseX, double mouseY, int button) { + return false; + } + + default boolean mouseScrolled(double mouseX, double mouseY, double mouseZ, double delta) { + return false; + } + + default void patternTypeChanged(PatternType newPatternType) { + // no op + } + + default void fuzzyModeChanged(boolean newFuzzyMode) { + // no op + } + + default boolean canInteractWithResourceSlot(ResourceSlot resourceSlot, + double mouseX, + double mouseY) { + return true; + } +} diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridScreen.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridScreen.java index 14db855e8..3b10fbd67 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridScreen.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternGridScreen.java @@ -1,45 +1,29 @@ package com.refinedmods.refinedstorage.common.autocrafting; -import com.refinedmods.refinedstorage.common.Platform; import com.refinedmods.refinedstorage.common.api.support.resource.PlatformResourceKey; import com.refinedmods.refinedstorage.common.grid.screen.AbstractGridScreen; import com.refinedmods.refinedstorage.common.support.containermenu.ResourceSlot; import com.refinedmods.refinedstorage.common.support.tooltip.SmallTextClientTooltipComponent; -import com.refinedmods.refinedstorage.common.support.widget.CustomCheckboxWidget; import com.refinedmods.refinedstorage.common.support.widget.HoveredImageButton; -import com.refinedmods.refinedstorage.common.support.widget.ScrollbarWidget; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import javax.annotation.Nullable; import com.mojang.datafixers.util.Pair; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.components.WidgetSprites; import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.inventory.CyclingSlotBackground; -import net.minecraft.client.gui.screens.inventory.InventoryScreen; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; -import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ArmorItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.SmithingTemplateItem; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.StonecutterRecipe; import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createIdentifier; import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createTranslation; @@ -48,27 +32,19 @@ public class PatternGridScreen extends AbstractGridScreen implements PatternGridContainerMenu.PatternGridListener { + static final int INSET_PADDING = 4; + static final int INSET_WIDTH = 138; + static final int INSET_HEIGHT = 71; + private static final ResourceLocation TEXTURE = createIdentifier("textures/gui/pattern_grid.png"); private static final MutableComponent CREATE_PATTERN = createTranslation("gui", "pattern_grid.create_pattern"); private static final MutableComponent CLEAR = createTranslation("gui", "pattern_grid.clear"); - private static final MutableComponent FUZZY_MODE = createTranslation("gui", "pattern_grid.fuzzy_mode"); - private static final MutableComponent FUZZY_MODE_ON_HELP = - createTranslation("gui", "pattern_grid.fuzzy_mode.on.help"); - private static final MutableComponent FUZZY_MODE_OFF_HELP = - createTranslation("gui", "pattern_grid.fuzzy_mode.off.help"); - private static final MutableComponent INPUTS = createTranslation("gui", "pattern_grid.processing.inputs"); - private static final MutableComponent OUTPUTS = createTranslation("gui", "pattern_grid.processing.outputs"); - private static final int CREATE_PATTERN_BUTTON_SIZE = 16; private static final SmallTextClientTooltipComponent CLICK_TO_CONFIGURE_AMOUNT_AND_ALTERNATIVES = new SmallTextClientTooltipComponent( createTranslationAsHeading("gui", "pattern_grid.processing.click_to_configure_amount_and_alternatives") ); - private static final int INSET_PADDING = 4; - private static final int PROCESSING_INSET_Y_PADDING = 9; - private static final int INSET_WIDTH = 138; - private static final int INSET_HEIGHT = 71; - + private static final int CREATE_PATTERN_BUTTON_SIZE = 16; private static final WidgetSprites CREATE_PATTERN_BUTTON_SPRITES = new WidgetSprites( createIdentifier("widget/create_pattern"), createIdentifier("widget/create_pattern_disabled"), @@ -81,37 +57,19 @@ public class PatternGridScreen extends AbstractGridScreen patternTypeButtons = new EnumMap<>(PatternType.class); private final Inventory playerInventory; private final Map>, ProcessingMatrixInputClientTooltipComponent> processingMatrixInputTooltipCache = new HashMap<>(); - - private final CyclingSlotBackground smithingTemplateIcon; - private final CyclingSlotBackground smithingBaseIcon; - private final CyclingSlotBackground smithingAdditionalIcon; + private final Map renderers = new EnumMap<>(PatternType.class); public PatternGridScreen(final PatternGridContainerMenu menu, final Inventory inventory, final Component title) { super(menu, inventory, title, 177); @@ -119,38 +77,34 @@ public PatternGridScreen(final PatternGridContainerMenu menu, final Inventory in this.imageWidth = 193; this.imageHeight = 249; this.playerInventory = inventory; - this.smithingTemplateIcon = new CyclingSlotBackground(menu.getFirstSmithingTableSlotIndex()); - this.smithingBaseIcon = new CyclingSlotBackground(menu.getFirstSmithingTableSlotIndex() + 1); - this.smithingAdditionalIcon = new CyclingSlotBackground(menu.getFirstSmithingTableSlotIndex() + 2); } @Override protected void init() { super.init(); + initRenderers(); this.createPatternButton = createCreatePatternButton(leftPos + 152, topPos + imageHeight - bottomHeight + 32); addRenderableWidget(createPatternButton); addPatternTypeButtons(getMenu().getPatternType()); - this.clearButton = createClearButton(getMenu().getPatternType()); + this.clearButton = createClearButton(); addRenderableWidget(clearButton); - this.fuzzyModeCheckbox = createFuzzyModeCheckbox(); - addRenderableWidget(fuzzyModeCheckbox); - this.processingScrollbar = createProcessingScrollbar(); - updateProcessingScrollbarMaxOffset(); - addWidget(processingScrollbar); - this.stonecutterScrollbar = createStonecutterScrollbar(); - updateStonecutterScrollbarMaxOffset(); - addWidget(stonecutterScrollbar); menu.setListener(this); - if (minecraft != null && minecraft.level != null) { - smithingTablePreview = new ArmorStand(minecraft.level, 0.0, 0.0, 0.0); - smithingTablePreview.setNoBasePlate(true); - smithingTablePreview.setShowArms(true); - smithingTablePreview.yBodyRot = 210.0F; - smithingTablePreview.setXRot(25.0F); - smithingTablePreview.yHeadRot = smithingTablePreview.getYRot(); - smithingTablePreview.yHeadRotO = smithingTablePreview.getYRot(); - smithingTableResult = getMenu().getSmithingTableResult().copy(); - updateArmorStandPreview(smithingTableResult); + } + + private void initRenderers() { + for (final PatternType type : PatternType.values()) { + final PatternGridRenderer typeRenderer = type.createRenderer( + menu, + leftPos, + topPos, + getInsetX(), + getInsetY() + ); + if (type == getMenu().getPatternType()) { + this.renderer = typeRenderer; + } + typeRenderer.addWidgets(this::addWidget, this::addRenderableWidget); + renderers.put(type, typeRenderer); } } @@ -185,10 +139,10 @@ private void addPatternTypeButtons(final PatternType currentPatternType) { } } - private HoveredImageButton createClearButton(final PatternType patternType) { + private HoveredImageButton createClearButton() { final HoveredImageButton button = new HoveredImageButton( - getClearButtonX(patternType), - getClearButtonY(patternType), + requireNonNull(renderer).getClearButtonX(), + requireNonNull(renderer).getClearButtonY(), CLEAR_BUTTON_SIZE, CLEAR_BUTTON_SIZE, CLEAR_BUTTON_SPRITES, @@ -199,375 +153,41 @@ private HoveredImageButton createClearButton(final PatternType patternType) { return button; } - private CustomCheckboxWidget createFuzzyModeCheckbox() { - final CustomCheckboxWidget checkbox = new CustomCheckboxWidget( - getInsetContentX(), - topPos + imageHeight - bottomHeight + 65, - FUZZY_MODE, - font, - getMenu().isFuzzyMode(), - CustomCheckboxWidget.Size.SMALL - ); - checkbox.setOnPressed((c, selected) -> getMenu().setFuzzyMode(selected)); - checkbox.setTooltip(getFuzzyModeTooltip(getMenu().isFuzzyMode())); - checkbox.visible = isFuzzyModeCheckboxVisible(); - return checkbox; - } - - private static Tooltip getFuzzyModeTooltip(final boolean fuzzyMode) { - return fuzzyMode ? Tooltip.create(FUZZY_MODE_ON_HELP) : Tooltip.create(FUZZY_MODE_OFF_HELP); - } - - private ScrollbarWidget createProcessingScrollbar() { - final ScrollbarWidget scrollbar = new ScrollbarWidget( - getInsetX() + 126, - getInsetY() + 14, - ScrollbarWidget.Type.SMALL, - 52 - ); - scrollbar.visible = isProcessingScrollbarVisible(); - scrollbar.setListener(offset -> onProcessingScrollbarChanged((int) offset)); - return scrollbar; - } - - private void onProcessingScrollbarChanged(final int offset) { - int inputRow = 0; - int outputRow = 0; - final int scrollbarOffset = (processingScrollbar != null && processingScrollbar.isSmoothScrolling()) - ? offset - : offset * PROCESSING_MATRIX_SLOT_SIZE; - for (int i = 0; i < getMenu().getResourceSlots().size(); ++i) { - final ResourceSlot slot = getMenu().getResourceSlots().get(i); - if (!(slot instanceof ProcessingMatrixResourceSlot matrixSlot)) { - continue; - } - final int row = matrixSlot.isInput() ? inputRow : outputRow; - final int slotY = getInsetContentY() - + PROCESSING_INSET_Y_PADDING + 1 - + (row * PROCESSING_MATRIX_SLOT_SIZE) - - scrollbarOffset - - topPos; - Platform.INSTANCE.setSlotY(getMenu().getResourceSlots().get(i), slotY); - if ((i + 1) % 3 == 0) { - if (matrixSlot.isInput()) { - inputRow++; - } else { - outputRow++; - } - } - } - } - - private ScrollbarWidget createStonecutterScrollbar() { - final ScrollbarWidget scrollbar = new ScrollbarWidget( - getInsetX() + 107, - getInsetY() + 9, - ScrollbarWidget.Type.NORMAL, - 54 - ); - scrollbar.visible = isStonecutterScrollbarVisible(); - return scrollbar; - } - @Override protected void containerTick() { super.containerTick(); if (createPatternButton != null) { createPatternButton.active = getMenu().canCreatePattern(); } - updateProcessingScrollbarMaxOffset(); - updateStonecutterScrollbarMaxOffset(); - updateSmithingTableState(); - } - - private void updateProcessingScrollbarMaxOffset() { - if (processingScrollbar == null || getMenu().getPatternType() != PatternType.PROCESSING) { - return; + if (renderer != null) { + renderer.tick(); } - - int filledInputSlots = 0; - int filledOutputSlots = 0; - int lastFilledInputSlot = 0; - int lastFilledOutputSlot = 0; - - for (int i = 0; i < getMenu().getResourceSlots().size(); ++i) { - final ResourceSlot resourceSlot = getMenu().getResourceSlots().get(i); - if (resourceSlot.isEmpty() || !(resourceSlot instanceof ProcessingMatrixResourceSlot matrixSlot)) { - continue; - } - if (matrixSlot.isInput()) { - filledInputSlots++; - lastFilledInputSlot = i; - } else { - filledOutputSlots++; - lastFilledOutputSlot = i - 81; - } - } - - final int maxFilledSlots = Math.max(filledInputSlots, filledOutputSlots); - final int maxFilledRows = Math.floorDiv(maxFilledSlots - 1, 3); - - final int maxLastFilledSlot = Math.max(lastFilledInputSlot, lastFilledOutputSlot); - final int maxLastFilledRow = Math.floorDiv(maxLastFilledSlot, 3) - 2; - - final int maxOffset = Math.max(maxFilledRows, maxLastFilledRow); - final int maxOffsetCorrected = processingScrollbar.isSmoothScrolling() - ? maxOffset * PROCESSING_MATRIX_SLOT_SIZE - : maxOffset; - - processingScrollbar.setMaxOffset(maxOffsetCorrected); - processingScrollbar.setEnabled(maxOffsetCorrected > 0); - } - - private void updateStonecutterScrollbarMaxOffset() { - if (stonecutterScrollbar == null || getMenu().getPatternType() != PatternType.STONECUTTER) { - return; - } - final int items = getMenu().getStonecutterRecipes().size(); - final int rows = Math.ceilDiv(items, VanillaConstants.STONECUTTER_RECIPES_PER_ROW); - final int maxOffset = rows - VanillaConstants.STONECUTTER_ROWS_VISIBLE; - final int maxOffsetCorrected = maxOffset * (stonecutterScrollbar.isSmoothScrolling() ? 18 : 1); - stonecutterScrollbar.setMaxOffset(maxOffsetCorrected); - stonecutterScrollbar.setEnabled(maxOffsetCorrected > 0); - } - - private void updateSmithingTableState() { - if (getMenu().getPatternType() != PatternType.SMITHING_TABLE) { - return; - } - final ItemStack result = getMenu().getSmithingTableResult(); - if (!ItemStack.isSameItemSameComponents(result, smithingTableResult)) { - smithingTableResult = result.copy(); - updateArmorStandPreview(result); - } - final Optional templateItem = getMenu().getSmithingTableTemplateItem(); - smithingTemplateIcon.tick(VanillaConstants.EMPTY_SLOT_SMITHING_TEMPLATES); - smithingBaseIcon.tick(templateItem.map(SmithingTemplateItem::getBaseSlotEmptyIcons).orElse(List.of())); - smithingAdditionalIcon.tick( - templateItem.map(SmithingTemplateItem::getAdditionalSlotEmptyIcons).orElse(List.of()) - ); } @Override public void render(final GuiGraphics graphics, final int mouseX, final int mouseY, final float partialTicks) { super.render(graphics, mouseX, mouseY, partialTicks); - if (processingScrollbar != null) { - processingScrollbar.render(graphics, mouseX, mouseY, partialTicks); - } - if (stonecutterScrollbar != null) { - stonecutterScrollbar.render(graphics, mouseX, mouseY, partialTicks); + if (renderer != null) { + renderer.render(graphics, mouseX, mouseY, partialTicks); } } @Override protected void renderBg(final GuiGraphics graphics, final float partialTicks, final int mouseX, final int mouseY) { super.renderBg(graphics, partialTicks, mouseX, mouseY); - final int insetContentX = getInsetContentX(); - final int insetContentY = getInsetContentY(); - switch (getMenu().getPatternType()) { - case CRAFTING -> graphics.blitSprite(CRAFTING, insetContentX, insetContentY, 130, 54); - case PROCESSING -> renderProcessingBackground(graphics, mouseX, mouseY, insetContentX, insetContentY); - case STONECUTTER -> renderStonecutterBackground(graphics, mouseX, mouseY, getInsetX(), getInsetY()); - case SMITHING_TABLE -> renderSmithingTableBackground(graphics, partialTicks, insetContentX, insetContentY); - } - } - - private void renderProcessingBackground(final GuiGraphics graphics, - final int mouseX, - final int mouseY, - final int insetContentX, - final int insetContentY) { - graphics.blitSprite(PROCESSING, insetContentX, insetContentY + PROCESSING_INSET_Y_PADDING, 130, 54); - renderProcessingMatrix( - graphics, - getInsetContentX() + 1, - getInsetContentX() + 1 + 52 + 1, // include the edge so we get the item counts properly - mouseX, - mouseY, - true - ); - renderProcessingMatrix( - graphics, - getInsetContentX() + INDIVIDUAL_PROCESSING_MATRIX_SIZE + 2 + 1, - getInsetContentX() + INDIVIDUAL_PROCESSING_MATRIX_SIZE + 2 + 1 + 52 + 1, - mouseX, - mouseY, - false - ); - } - - private void renderProcessingMatrix(final GuiGraphics graphics, - final int startX, - final int endX, - final int mouseX, - final int mouseY, - final boolean input) { - final int startY = getInsetY() + 14; - // include the edge so we get the item counts properly - final int endY = getInsetY() + 14 + 52 + 1; - graphics.enableScissor(startX, startY, endX, endY); - renderProcessingMatrixSlotBackground(graphics, input); - renderProcessingMatrixSlots(graphics, mouseX, mouseY, input); - graphics.disableScissor(); - } - - private void renderProcessingMatrixSlotBackground(final GuiGraphics graphics, final boolean input) { - final int x = getInsetContentX() + (!input ? INDIVIDUAL_PROCESSING_MATRIX_SIZE + 2 : 0); - final int startY = getInsetY() + PROCESSING_INSET_Y_PADDING - INDIVIDUAL_PROCESSING_MATRIX_SIZE; - final int endY = getInsetY() + PROCESSING_INSET_Y_PADDING + INDIVIDUAL_PROCESSING_MATRIX_SIZE; - final int scrollbarOffset = processingScrollbar != null ? (int) processingScrollbar.getOffset() : 0; - final int scrollbarOffsetCorrected = processingScrollbar != null && processingScrollbar.isSmoothScrolling() - ? scrollbarOffset - : scrollbarOffset * PROCESSING_MATRIX_SLOT_SIZE; - for (int i = 0; i < 9; ++i) { - final int y = (getInsetY() + 13) - + (i * INDIVIDUAL_PROCESSING_MATRIX_SIZE) - - scrollbarOffsetCorrected; - if (y < startY || y > endY) { - continue; - } - graphics.blitSprite( - PROCESSING_MATRIX, - x, - y, - INDIVIDUAL_PROCESSING_MATRIX_SIZE, - INDIVIDUAL_PROCESSING_MATRIX_SIZE - ); - } - } - - private void renderProcessingMatrixSlots(final GuiGraphics graphics, - final int mouseX, - final int mouseY, - final boolean input) { - for (final ResourceSlot resourceSlot : getMenu().getResourceSlots()) { - if (resourceSlot.isActive() - && resourceSlot instanceof ProcessingMatrixResourceSlot matrixSlot - && matrixSlot.isInput() == input) { - tryRenderResourceSlot(graphics, resourceSlot); - if (isHovering(resourceSlot.x, resourceSlot.y, 16, 16, mouseX, mouseY) - && canInteractWithResourceSlot(resourceSlot, mouseX, mouseY)) { - renderSlotHighlight(graphics, leftPos + resourceSlot.x, topPos + resourceSlot.y, 0); - } - } - } - } - - private void renderStonecutterBackground(final GuiGraphics graphics, - final int mouseX, - final int mouseY, - final int insetX, - final int insetY) { - graphics.blitSprite(STONECUTTER, insetX + 8, insetY + 8, 112, 56); - graphics.enableScissor(insetX + 40, insetY + 9, insetX + 40 + 64, insetY + 9 + 54); - final boolean isOverArea = isOverStonecutterArea(mouseX, mouseY); - for (int i = 0; i < getMenu().getStonecutterRecipes().size(); ++i) { - final RecipeHolder recipe = getMenu().getStonecutterRecipes().get(i); - final int xx = getStonecutterRecipeX(insetX, i); - final int row = i / VanillaConstants.STONECUTTER_RECIPES_PER_ROW; - final int yy = getStonecutterRecipeY(insetY, row); - if (yy < insetY + 9 - 18 || yy > insetY + 9 + 54) { - continue; - } - final boolean hovering = mouseX >= xx && mouseY >= yy && mouseX < xx + 16 && mouseY < yy + 18; - final ResourceLocation buttonSprite; - if (i == getMenu().getStonecutterSelectedRecipe()) { - buttonSprite = VanillaConstants.STONECUTTER_RECIPE_SELECTED_SPRITE; - } else if (isOverArea && hovering) { - buttonSprite = VanillaConstants.STONECUTTER_RECIPE_HIGHLIGHTED_SPRITE; - } else { - buttonSprite = VanillaConstants.STONECUTTER_RECIPE_SPRITE; - } - graphics.blitSprite(buttonSprite, xx, yy, 16, 18); - graphics.renderItem( - recipe.value().getResultItem(requireNonNull(minecraft).level.registryAccess()), - xx, - yy + 1 - ); - } - graphics.disableScissor(); - } - - private void renderSmithingTableBackground(final GuiGraphics graphics, - final float partialTicks, - final int insetContentX, - final int insetContentY) { - graphics.blitSprite(SMITHING_TABLE, insetContentX, getInsetY() + 26, 98, 18); - smithingTemplateIcon.render(menu, graphics, partialTicks, leftPos, topPos); - smithingBaseIcon.render(menu, graphics, partialTicks, leftPos, topPos); - smithingAdditionalIcon.render(menu, graphics, partialTicks, leftPos, topPos); - if (smithingTablePreview != null) { - InventoryScreen.renderEntityInInventory( - graphics, - (float) (leftPos + 133), - (float) (insetContentY + 54), - 25.0F, - VanillaConstants.ARMOR_STAND_TRANSLATION, - VanillaConstants.ARMOR_STAND_ANGLE, - null, - smithingTablePreview - ); + if (renderer != null) { + renderer.renderBackground(graphics, partialTicks, mouseX, mouseY); } } @Override protected void renderTooltip(final GuiGraphics graphics, final int x, final int y) { super.renderTooltip(graphics, x, y); - renderStonecutterHoveredRecipeTooltip(graphics, x, y); - renderSmithingTableHelpTooltips(graphics, x, y); - } - - private void renderStonecutterHoveredRecipeTooltip(final GuiGraphics graphics, final int x, final int y) { - if (getMenu().getPatternType() != PatternType.STONECUTTER || !isOverStonecutterArea(x, y)) { - return; - } - final int insetX = getInsetX(); - final int insetY = getInsetY(); - for (int i = 0; i < getMenu().getStonecutterRecipes().size(); ++i) { - final RecipeHolder recipe = getMenu().getStonecutterRecipes().get(i); - final ItemStack result = recipe.value().getResultItem(requireNonNull(minecraft).level.registryAccess()); - final int xx = getStonecutterRecipeX(insetX, i); - final int row = i / VanillaConstants.STONECUTTER_RECIPES_PER_ROW; - final int yy = getStonecutterRecipeY(insetY, row); - if (yy < insetY + 9 - 18 || yy > insetY + 9 + 54) { - continue; - } - if (x >= xx && y >= yy && x < xx + 16 && y < yy + 18) { - graphics.renderTooltip(font, result, x, y); - } + if (renderer != null) { + renderer.renderTooltip(font, hoveredSlot, graphics, x, y); } } - private void renderSmithingTableHelpTooltips(final GuiGraphics graphics, final int x, final int y) { - if (getMenu().getPatternType() != PatternType.SMITHING_TABLE || hoveredSlot == null || hoveredSlot.hasItem()) { - return; - } - final int firstSlotIndex = getMenu().getFirstSmithingTableSlotIndex(); - getMenu().getSmithingTableTemplateItem().ifPresentOrElse(template -> { - if (hoveredSlot.index == firstSlotIndex + 1) { - graphics.renderTooltip(font, font.split(template.getBaseSlotDescription(), 115), x, y); - } else if (hoveredSlot.index == firstSlotIndex + 2) { - graphics.renderTooltip(font, font.split(template.getAdditionSlotDescription(), 115), x, y); - } - }, () -> { - if (hoveredSlot.index == firstSlotIndex) { - graphics.renderTooltip(font, font.split(VanillaConstants.MISSING_SMITHING_TEMPLATE_TOOLTIP, 115), x, y); - } - }); - } - - private int getStonecutterRecipeX(final int insetX, final int i) { - return insetX + 40 + i % VanillaConstants.STONECUTTER_RECIPES_PER_ROW * 16; - } - - private int getStonecutterRecipeY(final int insetY, final int row) { - return insetY - + 9 - + (row * 18) - - ((stonecutterScrollbar != null ? (int) stonecutterScrollbar.getOffset() : 0) - * (stonecutterScrollbar != null && stonecutterScrollbar.isSmoothScrolling() ? 1 : 18)); - } - @Override protected void renderResourceSlots(final GuiGraphics graphics) { // no op, we render them in the scissor rendering @@ -577,18 +197,7 @@ protected void renderResourceSlots(final GuiGraphics graphics) { protected boolean canInteractWithResourceSlot(final ResourceSlot resourceSlot, final double mouseX, final double mouseY) { - // Ensure that we can't interact with the resource slot, when the resource slot is on the - // edge of the scissoring area and still technically visible and active, - // but we're no longer hovering over the processing matrix. - final int insetContentX = getInsetContentX() + ( - resourceSlot instanceof ProcessingMatrixResourceSlot matrixSlot && !matrixSlot.isInput() - ? INDIVIDUAL_PROCESSING_MATRIX_SIZE + 2 - : 0); - final int insetContentY = getInsetContentY(); - return mouseX >= insetContentX - && mouseX < insetContentX + INDIVIDUAL_PROCESSING_MATRIX_SIZE - && mouseY >= insetContentY + PROCESSING_INSET_Y_PADDING - && mouseY < insetContentY + PROCESSING_INSET_Y_PADDING + INDIVIDUAL_PROCESSING_MATRIX_SIZE; + return renderer != null && renderer.canInteractWithResourceSlot(resourceSlot, mouseX, mouseY); } @Override @@ -630,166 +239,64 @@ protected Screen createResourceAmountScreen(final ResourceSlot slot) { @Override protected void renderLabels(final GuiGraphics graphics, final int mouseX, final int mouseY) { super.renderLabels(graphics, mouseX, mouseY); - if (getMenu().getPatternType() == PatternType.PROCESSING) { - final int x = getInsetContentX() - leftPos; - final int y = getInsetContentY() - topPos - 1; - graphics.drawString(font, INPUTS, x, y, 4210752, false); - graphics.drawString(font, OUTPUTS, x + 56, y, 4210752, false); + if (renderer != null) { + renderer.renderLabels(graphics, font, mouseX, mouseY); } } @Override public boolean mouseClicked(final double mouseX, final double mouseY, final int clickedButton) { - if (processingScrollbar != null && processingScrollbar.mouseClicked(mouseX, mouseY, clickedButton)) { - return true; - } - if (stonecutterScrollbar != null && stonecutterScrollbar.mouseClicked(mouseX, mouseY, clickedButton)) { - return true; - } - if (clickedStonecutterRecipe(mouseX, mouseY)) { + final boolean clickedInRecipe = renderer != null && renderer.mouseClicked(mouseX, mouseY, clickedButton); + if (clickedInRecipe) { return true; } return super.mouseClicked(mouseX, mouseY, clickedButton); } - private boolean clickedStonecutterRecipe(final double x, final double y) { - if (getMenu().getPatternType() != PatternType.STONECUTTER || !isOverStonecutterArea(x, y)) { - return false; - } - final int insetX = getInsetX(); - final int insetY = getInsetY(); - for (int i = 0; i < getMenu().getStonecutterRecipes().size(); ++i) { - final int xx = getStonecutterRecipeX(insetX, i); - final int row = i / VanillaConstants.STONECUTTER_RECIPES_PER_ROW; - final int yy = getStonecutterRecipeY(insetY, row); - if (yy < insetY + 9 - 18 || yy > insetY + 9 + 54) { - continue; - } - if (x >= xx && y >= yy && x < xx + 16 && y < yy + 18) { - getMenu().setStonecutterSelectedRecipe(i); - Minecraft.getInstance().getSoundManager().play( - SimpleSoundInstance.forUI(SoundEvents.UI_STONECUTTER_SELECT_RECIPE, 1.0F) - ); - return true; - } - } - return false; - } - @Override public void mouseMoved(final double mx, final double my) { - if (processingScrollbar != null) { - processingScrollbar.mouseMoved(mx, my); - } - if (stonecutterScrollbar != null) { - stonecutterScrollbar.mouseMoved(mx, my); + if (renderer != null) { + renderer.mouseMoved(mx, my); } super.mouseMoved(mx, my); } @Override public boolean mouseReleased(final double mx, final double my, final int button) { - if (processingScrollbar == null || stonecutterScrollbar == null) { - return super.mouseReleased(mx, my, button); - } - return processingScrollbar.mouseReleased(mx, my, button) - || stonecutterScrollbar.mouseReleased(mx, my, button) + return (renderer != null && renderer.mouseReleased(mx, my, button)) || super.mouseReleased(mx, my, button); } @Override public boolean mouseScrolled(final double x, final double y, final double z, final double delta) { - return tryProcessingScrollbar(x, y, z, delta) - || tryStonecutterScrollbar(x, y, z, delta) + return (renderer != null && renderer.mouseScrolled(x, y, z, delta)) || super.mouseScrolled(x, y, z, delta); } - private boolean tryProcessingScrollbar(final double x, final double y, final double z, final double delta) { - final boolean isOverProcessingArea = x >= getInsetX() - && (x < getInsetX() + INSET_WIDTH) - && y > getInsetY() - && (y < getInsetY() + INSET_HEIGHT); - return processingScrollbar != null - && processingScrollbar.isActive() - && isOverProcessingArea - && processingScrollbar.mouseScrolled(x, y, z, delta); - } - - private boolean tryStonecutterScrollbar(final double x, final double y, final double z, final double delta) { - return stonecutterScrollbar != null - && stonecutterScrollbar.isActive() - && isOverStonecutterArea(x, y) - && stonecutterScrollbar.mouseScrolled(x, y, z, delta); - } - - private boolean isOverStonecutterArea(final double x, final double y) { - return x >= getInsetX() + 40 - && (x < getInsetX() + 40 + 81) - && y > getInsetY() + 8 - && (y < getInsetY() + 8 + 56); - } - @Override protected ResourceLocation getTexture() { return TEXTURE; } @Override - public void patternTypeChanged(final PatternType value) { + public void patternTypeChanged(final PatternType newPatternType) { patternTypeButtons.values().forEach(button -> button.setSelected(false)); - patternTypeButtons.get(value).setSelected(true); - if (fuzzyModeCheckbox != null) { - fuzzyModeCheckbox.visible = isFuzzyModeCheckboxVisible(); + patternTypeButtons.get(newPatternType).setSelected(true); + if (renderer != null) { + renderer.patternTypeChanged(newPatternType); } + this.renderer = requireNonNull(renderers.get(newPatternType)); + this.renderer.patternTypeChanged(newPatternType); if (clearButton != null) { - clearButton.setX(getClearButtonX(value)); - requireNonNull(clearButton).setY(getClearButtonY(value)); - } - if (processingScrollbar != null) { - processingScrollbar.visible = isProcessingScrollbarVisible(); - } - if (stonecutterScrollbar != null) { - stonecutterScrollbar.visible = isStonecutterScrollbarVisible(); + clearButton.setPosition(renderer.getClearButtonX(), renderer.getClearButtonY()); } } @Override - public void fuzzyModeChanged(final boolean value) { - if (fuzzyModeCheckbox == null) { - return; + public void fuzzyModeChanged(final boolean newFuzzyMode) { + if (renderer != null) { + renderer.fuzzyModeChanged(newFuzzyMode); } - fuzzyModeCheckbox.setSelected(value); - fuzzyModeCheckbox.setTooltip(getFuzzyModeTooltip(value)); - } - - private int getClearButtonX(final PatternType patternType) { - return switch (patternType) { - case CRAFTING -> leftPos + 69; - case PROCESSING -> leftPos + 124; - case STONECUTTER -> leftPos + 131; - case SMITHING_TABLE -> leftPos + 112; - }; - } - - private int getClearButtonY(final PatternType patternType) { - return switch (patternType) { - case PROCESSING -> getInsetContentY() + PROCESSING_INSET_Y_PADDING; - case STONECUTTER -> getInsetY() + 8; - case SMITHING_TABLE -> getInsetY() + 26; - default -> getInsetContentY(); - }; - } - - private boolean isFuzzyModeCheckboxVisible() { - return getMenu().getPatternType() == PatternType.CRAFTING; - } - - private boolean isProcessingScrollbarVisible() { - return getMenu().getPatternType() == PatternType.PROCESSING; - } - - private boolean isStonecutterScrollbarVisible() { - return getMenu().getPatternType() == PatternType.STONECUTTER; } private int getInsetX() { @@ -799,29 +306,4 @@ private int getInsetX() { private int getInsetY() { return topPos + imageHeight - bottomHeight + 5; } - - private int getInsetContentX() { - return getInsetX() + INSET_PADDING; - } - - private int getInsetContentY() { - return getInsetY() + INSET_PADDING; - } - - private void updateArmorStandPreview(final ItemStack result) { - if (smithingTablePreview == null) { - return; - } - for (final EquipmentSlot equipmentslot : EquipmentSlot.values()) { - smithingTablePreview.setItemSlot(equipmentslot, ItemStack.EMPTY); - } - if (result.isEmpty()) { - return; - } - if (result.getItem() instanceof ArmorItem armorItem) { - smithingTablePreview.setItemSlot(armorItem.getEquipmentSlot(), result); - } else { - smithingTablePreview.setItemSlot(EquipmentSlot.OFFHAND, result); - } - } } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternType.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternType.java index da21cffd7..547fd3c83 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternType.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/PatternType.java @@ -34,6 +34,19 @@ Component getTranslatedName() { return translatedName; } + PatternGridRenderer createRenderer(final PatternGridContainerMenu menu, + final int leftPos, + final int topPos, + final int x, + final int y) { + return switch (this) { + case CRAFTING -> new CraftingPatternGridRenderer(menu, leftPos, x, y); + case PROCESSING -> new ProcessingPatternGridRenderer(menu, leftPos, topPos, x, y); + case STONECUTTER -> new StonecutterPatternGridRenderer(menu, leftPos, x, y); + case SMITHING_TABLE -> new SmithingTablePatternGridRenderer(menu, leftPos, topPos, x, y); + }; + } + @Override public String getSerializedName() { return name; diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/ProcessingPatternClientTooltipComponent.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/ProcessingPatternClientTooltipComponent.java index c4c3c2827..2a5d22278 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/ProcessingPatternClientTooltipComponent.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/ProcessingPatternClientTooltipComponent.java @@ -4,7 +4,7 @@ import com.refinedmods.refinedstorage.common.api.RefinedStorageApi; import com.refinedmods.refinedstorage.common.api.support.resource.PlatformResourceKey; import com.refinedmods.refinedstorage.common.api.support.resource.ResourceRendering; -import com.refinedmods.refinedstorage.common.support.AbstractBaseScreen; +import com.refinedmods.refinedstorage.common.support.ResourceSlotRendering; import java.util.List; import java.util.stream.Stream; @@ -155,8 +155,7 @@ private void renderMatrixSlot( resourceAmount.resource() ); rendering.render(resourceAmount.resource(), graphics, slotX + 1, slotY + 1); - AbstractBaseScreen.renderResourceAmount(graphics, slotX + 1, slotY + 1, resourceAmount.amount(), - rendering); + ResourceSlotRendering.render(graphics, slotX + 1, slotY + 1, resourceAmount.amount(), rendering); } private void renderOutputText(final Font font, final int x, final int y, final GuiGraphics graphics) { diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/ProcessingPatternGridRenderer.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/ProcessingPatternGridRenderer.java new file mode 100644 index 000000000..25ffd1fdf --- /dev/null +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/ProcessingPatternGridRenderer.java @@ -0,0 +1,309 @@ +package com.refinedmods.refinedstorage.common.autocrafting; + +import com.refinedmods.refinedstorage.common.Platform; +import com.refinedmods.refinedstorage.common.support.ResourceSlotRendering; +import com.refinedmods.refinedstorage.common.support.containermenu.ResourceSlot; +import com.refinedmods.refinedstorage.common.support.widget.ScrollbarWidget; + +import java.util.function.Consumer; +import javax.annotation.Nullable; + +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; + +import static com.refinedmods.refinedstorage.common.autocrafting.PatternGridScreen.INSET_HEIGHT; +import static com.refinedmods.refinedstorage.common.autocrafting.PatternGridScreen.INSET_PADDING; +import static com.refinedmods.refinedstorage.common.autocrafting.PatternGridScreen.INSET_WIDTH; +import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createIdentifier; +import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createTranslation; +import static net.minecraft.client.gui.screens.inventory.AbstractContainerScreen.renderSlotHighlight; + +class ProcessingPatternGridRenderer implements PatternGridRenderer { + private static final ResourceLocation PROCESSING = createIdentifier("pattern_grid/processing"); + private static final ResourceLocation PROCESSING_MATRIX = createIdentifier("pattern_grid/processing_matrix"); + private static final int INDIVIDUAL_PROCESSING_MATRIX_SIZE = 54; + private static final int PROCESSING_MATRIX_SLOT_SIZE = 18; + private static final int PROCESSING_INSET_Y_PADDING = 9; + private static final MutableComponent INPUTS = createTranslation("gui", "pattern_grid.processing.inputs"); + private static final MutableComponent OUTPUTS = createTranslation("gui", "pattern_grid.processing.outputs"); + + private final PatternGridContainerMenu menu; + private final int leftPos; + private final int topPos; + private final int x; + private final int y; + + @Nullable + private ScrollbarWidget scrollbar; + + ProcessingPatternGridRenderer(final PatternGridContainerMenu menu, + final int leftPos, + final int topPos, + final int x, + final int y) { + this.menu = menu; + this.leftPos = leftPos; + this.topPos = topPos; + this.x = x; + this.y = y; + } + + @Override + public void addWidgets(final Consumer widgets, final Consumer renderables) { + scrollbar = createProcessingScrollbar(); + updateScrollbarMaxOffset(); + widgets.accept(scrollbar); + } + + private void updateScrollbarMaxOffset() { + if (scrollbar == null) { + return; + } + + int filledInputSlots = 0; + int filledOutputSlots = 0; + int lastFilledInputSlot = 0; + int lastFilledOutputSlot = 0; + + for (int i = 0; i < menu.getResourceSlots().size(); ++i) { + final ResourceSlot resourceSlot = menu.getResourceSlots().get(i); + if (resourceSlot.isEmpty() || !(resourceSlot instanceof ProcessingMatrixResourceSlot matrixSlot)) { + continue; + } + if (matrixSlot.isInput()) { + filledInputSlots++; + lastFilledInputSlot = i; + } else { + filledOutputSlots++; + lastFilledOutputSlot = i - 81; + } + } + + final int maxFilledSlots = Math.max(filledInputSlots, filledOutputSlots); + final int maxFilledRows = Math.floorDiv(maxFilledSlots - 1, 3); + + final int maxLastFilledSlot = Math.max(lastFilledInputSlot, lastFilledOutputSlot); + final int maxLastFilledRow = Math.floorDiv(maxLastFilledSlot, 3) - 2; + + final int maxOffset = Math.max(maxFilledRows, maxLastFilledRow); + final int maxOffsetCorrected = scrollbar.isSmoothScrolling() + ? maxOffset * PROCESSING_MATRIX_SLOT_SIZE + : maxOffset; + + scrollbar.setMaxOffset(maxOffsetCorrected); + scrollbar.setEnabled(maxOffsetCorrected > 0); + } + + private ScrollbarWidget createProcessingScrollbar() { + final ScrollbarWidget s = new ScrollbarWidget( + x + 126, + y + 14, + ScrollbarWidget.Type.SMALL, + 52 + ); + s.visible = isScrollbarVisible(menu); + s.setListener(offset -> onScrollbarChanged((int) offset)); + return s; + } + + private void onScrollbarChanged(final int offset) { + int inputRow = 0; + int outputRow = 0; + final int scrollbarOffset = (scrollbar != null && scrollbar.isSmoothScrolling()) + ? offset + : offset * PROCESSING_MATRIX_SLOT_SIZE; + for (int i = 0; i < menu.getResourceSlots().size(); ++i) { + final ResourceSlot slot = menu.getResourceSlots().get(i); + if (!(slot instanceof ProcessingMatrixResourceSlot matrixSlot)) { + continue; + } + final int row = matrixSlot.isInput() ? inputRow : outputRow; + final int slotY = y + + INSET_PADDING + + PROCESSING_INSET_Y_PADDING + 1 + + (row * PROCESSING_MATRIX_SLOT_SIZE) + - scrollbarOffset + - topPos; + Platform.INSTANCE.setSlotY(menu.getResourceSlots().get(i), slotY); + if ((i + 1) % 3 == 0) { + if (matrixSlot.isInput()) { + inputRow++; + } else { + outputRow++; + } + } + } + } + + private static boolean isScrollbarVisible(final PatternGridContainerMenu menu) { + return menu.getPatternType() == PatternType.PROCESSING; + } + + @Override + public void tick() { + updateScrollbarMaxOffset(); + } + + @Override + public void render(final GuiGraphics graphics, + final int mouseX, + final int mouseY, + final float partialTicks) { + if (scrollbar != null) { + scrollbar.render(graphics, mouseX, mouseY, partialTicks); + } + } + + @Override + public int getClearButtonX() { + return leftPos + 124; + } + + @Override + public int getClearButtonY() { + return y + INSET_PADDING + PROCESSING_INSET_Y_PADDING; + } + + @Override + public void renderBackground(final GuiGraphics graphics, + final float partialTicks, + final int mouseX, + final int mouseY) { + graphics.blitSprite(PROCESSING, x + INSET_PADDING, y + INSET_PADDING + PROCESSING_INSET_Y_PADDING, 130, 54); + renderMatrix( + graphics, + x + INSET_PADDING + 1, + x + INSET_PADDING + 1 + 52 + 1, // include the edge so we get the item counts properly + mouseX, + mouseY, + true + ); + renderMatrix( + graphics, + x + INSET_PADDING + INDIVIDUAL_PROCESSING_MATRIX_SIZE + 2 + 1, + x + INSET_PADDING + INDIVIDUAL_PROCESSING_MATRIX_SIZE + 2 + 1 + 52 + 1, + mouseX, + mouseY, + false + ); + } + + private void renderMatrix(final GuiGraphics graphics, + final int startX, + final int endX, + final int mouseX, + final int mouseY, + final boolean input) { + final int startY = y + 14; + // include the edge so we get the item counts properly + final int endY = y + 14 + 52 + 1; + graphics.enableScissor(startX, startY, endX, endY); + renderMatrix(graphics, input); + renderMatrixSlots(graphics, mouseX, mouseY, input); + graphics.disableScissor(); + } + + private void renderMatrix(final GuiGraphics graphics, final boolean input) { + final int xx = x + INSET_PADDING + (!input ? INDIVIDUAL_PROCESSING_MATRIX_SIZE + 2 : 0); + final int startY = y + PROCESSING_INSET_Y_PADDING - INDIVIDUAL_PROCESSING_MATRIX_SIZE; + final int endY = y + PROCESSING_INSET_Y_PADDING + INDIVIDUAL_PROCESSING_MATRIX_SIZE; + final int scrollbarOffset = scrollbar != null ? (int) scrollbar.getOffset() : 0; + final int scrollbarOffsetCorrected = scrollbar != null && scrollbar.isSmoothScrolling() + ? scrollbarOffset + : scrollbarOffset * PROCESSING_MATRIX_SLOT_SIZE; + for (int i = 0; i < 9; ++i) { + final int yy = (y + 13) + + (i * INDIVIDUAL_PROCESSING_MATRIX_SIZE) + - scrollbarOffsetCorrected; + if (yy < startY || yy > endY) { + continue; + } + graphics.blitSprite( + PROCESSING_MATRIX, + xx, + yy, + INDIVIDUAL_PROCESSING_MATRIX_SIZE, + INDIVIDUAL_PROCESSING_MATRIX_SIZE + ); + } + } + + private void renderMatrixSlots(final GuiGraphics graphics, + final int mouseX, + final int mouseY, + final boolean input) { + for (final ResourceSlot resourceSlot : menu.getResourceSlots()) { + if (resourceSlot.isActive() + && resourceSlot instanceof ProcessingMatrixResourceSlot matrixSlot + && matrixSlot.isInput() == input) { + ResourceSlotRendering.render(graphics, resourceSlot, leftPos, topPos); + final boolean hovering = mouseX >= resourceSlot.x + leftPos + && mouseX < resourceSlot.x + leftPos + 16 + && mouseY >= resourceSlot.y + topPos + && mouseY < resourceSlot.y + topPos + 16; + if (hovering && canInteractWithResourceSlot(resourceSlot, mouseX, mouseY)) { + renderSlotHighlight(graphics, leftPos + resourceSlot.x, topPos + resourceSlot.y, 0); + } + } + } + } + + @Override + public boolean canInteractWithResourceSlot(final ResourceSlot resourceSlot, + final double mouseX, + final double mouseY) { + final int insetContentX = x + INSET_PADDING + ( + resourceSlot instanceof ProcessingMatrixResourceSlot matrixSlot && !matrixSlot.isInput() + ? INDIVIDUAL_PROCESSING_MATRIX_SIZE + 2 + : 0); + final int insetContentY = y + INSET_PADDING; + return mouseX >= insetContentX + && mouseX < insetContentX + INDIVIDUAL_PROCESSING_MATRIX_SIZE + && mouseY >= insetContentY + PROCESSING_INSET_Y_PADDING + && mouseY < insetContentY + PROCESSING_INSET_Y_PADDING + INDIVIDUAL_PROCESSING_MATRIX_SIZE; + } + + @Override + public void renderLabels(final GuiGraphics graphics, final Font font, final int mouseX, final int mouseY) { + final int xx = x - leftPos + INSET_PADDING; + final int yy = y - topPos - 1 + INSET_PADDING; + graphics.drawString(font, INPUTS, xx, yy, 4210752, false); + graphics.drawString(font, OUTPUTS, xx + 56, yy, 4210752, false); + + } + + @Override + public boolean mouseClicked(final double mouseX, final double mouseY, final int clickedButton) { + return scrollbar != null && scrollbar.mouseClicked(mouseX, mouseY, clickedButton); + } + + @Override + public void mouseMoved(final double mouseX, final double mouseY) { + if (scrollbar != null) { + scrollbar.mouseMoved(mouseX, mouseY); + } + } + + @Override + public boolean mouseReleased(final double mouseX, final double mouseY, final int button) { + return scrollbar != null && scrollbar.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseScrolled(final double mouseX, final double mouseY, final double mouseZ, final double delta) { + if (!(mouseX >= x && (mouseX < x + INSET_WIDTH) && mouseY > y && (mouseY < y + INSET_HEIGHT))) { + return false; + } + return scrollbar != null && scrollbar.mouseScrolled(mouseX, mouseY, mouseZ, delta); + } + + @Override + public void patternTypeChanged(final PatternType newPatternType) { + if (scrollbar != null) { + scrollbar.visible = isScrollbarVisible(menu); + } + } +} diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/SmithingTablePatternGridRenderer.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/SmithingTablePatternGridRenderer.java new file mode 100644 index 000000000..bb9ef3ce4 --- /dev/null +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/SmithingTablePatternGridRenderer.java @@ -0,0 +1,180 @@ +package com.refinedmods.refinedstorage.common.autocrafting; + +import com.refinedmods.refinedstorage.common.util.PlatformUtil; + +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; +import javax.annotation.Nullable; + +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.screens.inventory.CyclingSlotBackground; +import net.minecraft.client.gui.screens.inventory.InventoryScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.SmithingTemplateItem; +import net.minecraft.world.level.Level; + +import static com.refinedmods.refinedstorage.common.autocrafting.PatternGridScreen.INSET_HEIGHT; +import static com.refinedmods.refinedstorage.common.autocrafting.PatternGridScreen.INSET_PADDING; +import static com.refinedmods.refinedstorage.common.autocrafting.PatternGridScreen.INSET_WIDTH; +import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createIdentifier; + +class SmithingTablePatternGridRenderer implements PatternGridRenderer { + private static final ResourceLocation SPRITE = createIdentifier("pattern_grid/smithing_table"); + + private final PatternGridContainerMenu menu; + private final int leftPos; + private final int topPos; + private final int x; + private final int y; + private final CyclingSlotBackground templateIcon; + private final CyclingSlotBackground baseIcon; + private final CyclingSlotBackground additionalIcon; + + @Nullable + private ArmorStand preview; + private ItemStack result = ItemStack.EMPTY; + + SmithingTablePatternGridRenderer(final PatternGridContainerMenu menu, + final int leftPos, + final int topPos, + final int x, + final int y) { + this.menu = menu; + this.leftPos = leftPos; + this.topPos = topPos; + this.x = x; + this.y = y; + this.templateIcon = new CyclingSlotBackground(menu.getFirstSmithingTableSlotIndex()); + this.baseIcon = new CyclingSlotBackground(menu.getFirstSmithingTableSlotIndex() + 1); + this.additionalIcon = new CyclingSlotBackground(menu.getFirstSmithingTableSlotIndex() + 2); + } + + @Override + public void addWidgets(final Consumer widgets, + final Consumer renderables) { + final Level level = PlatformUtil.getClientLevel(); + if (level == null) { + return; + } + preview = new ArmorStand(level, 0.0, 0.0, 0.0); + preview.setNoBasePlate(true); + preview.setShowArms(true); + preview.yBodyRot = 210.0F; + preview.setXRot(25.0F); + preview.yHeadRot = preview.getYRot(); + preview.yHeadRotO = preview.getYRot(); + result = menu.getSmithingTableResult().copy(); + updatePreview(); + } + + @Override + public void tick() { + final ItemStack currentResult = menu.getSmithingTableResult(); + if (!ItemStack.isSameItemSameComponents(currentResult, result)) { + result = currentResult.copy(); + updatePreview(); + } + final Optional templateItem = menu.getSmithingTableTemplateItem(); + templateIcon.tick(VanillaConstants.EMPTY_SLOT_SMITHING_TEMPLATES); + baseIcon.tick(templateItem.map(SmithingTemplateItem::getBaseSlotEmptyIcons).orElse(List.of())); + additionalIcon.tick(templateItem.map(SmithingTemplateItem::getAdditionalSlotEmptyIcons).orElse(List.of())); + } + + @Override + public int getClearButtonX() { + return leftPos + 112; + } + + @Override + public int getClearButtonY() { + return y + 26; + } + + @Override + public void renderBackground(final GuiGraphics graphics, + final float partialTicks, + final int mouseX, + final int mouseY) { + graphics.enableScissor(x, y, x + INSET_WIDTH, y + INSET_HEIGHT); + graphics.blitSprite(SPRITE, x + INSET_PADDING, y + 26, 98, 18); + renderIcons(graphics, partialTicks); + if (preview != null) { + InventoryScreen.renderEntityInInventory( + graphics, + (float) (x + 128), + (float) (y + 52), + 25.0F, + VanillaConstants.ARMOR_STAND_TRANSLATION, + VanillaConstants.ARMOR_STAND_ANGLE, + null, + preview + ); + } + graphics.disableScissor(); + } + + private void renderIcons(final GuiGraphics graphics, final float partialTicks) { + templateIcon.render(menu, graphics, partialTicks, leftPos, topPos); + baseIcon.render(menu, graphics, partialTicks, leftPos, topPos); + additionalIcon.render(menu, graphics, partialTicks, leftPos, topPos); + } + + @Override + public void renderTooltip(final Font font, + @Nullable final Slot hoveredSlot, + final GuiGraphics graphics, + final int mouseX, + final int mouseY) { + if (hoveredSlot == null || hoveredSlot.hasItem()) { + return; + } + final int firstSlotIndex = menu.getFirstSmithingTableSlotIndex(); + menu.getSmithingTableTemplateItem().ifPresentOrElse(template -> { + if (hoveredSlot.index == firstSlotIndex + 1) { + graphics.renderTooltip(font, split(font, template.getBaseSlotDescription()), mouseX, mouseY); + } else if (hoveredSlot.index == firstSlotIndex + 2) { + graphics.renderTooltip(font, split(font, template.getAdditionSlotDescription()), mouseX, mouseY); + } + }, () -> { + if (hoveredSlot.index == firstSlotIndex) { + graphics.renderTooltip( + font, + split(font, VanillaConstants.MISSING_SMITHING_TEMPLATE_TOOLTIP), + mouseX, + mouseY + ); + } + }); + } + + private static List split(final Font font, final Component template) { + return font.split(template, 115); + } + + private void updatePreview() { + if (preview == null) { + return; + } + for (final EquipmentSlot equipmentslot : EquipmentSlot.values()) { + preview.setItemSlot(equipmentslot, ItemStack.EMPTY); + } + if (result.isEmpty()) { + return; + } + if (result.getItem() instanceof ArmorItem armorItem) { + preview.setItemSlot(armorItem.getEquipmentSlot(), result); + } else { + preview.setItemSlot(EquipmentSlot.OFFHAND, result); + } + } +} diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/StonecutterPatternGridRenderer.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/StonecutterPatternGridRenderer.java new file mode 100644 index 000000000..cb7551b3c --- /dev/null +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/StonecutterPatternGridRenderer.java @@ -0,0 +1,243 @@ +package com.refinedmods.refinedstorage.common.autocrafting; + +import com.refinedmods.refinedstorage.common.support.widget.ScrollbarWidget; +import com.refinedmods.refinedstorage.common.util.PlatformUtil; + +import java.util.function.Consumer; +import javax.annotation.Nullable; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.StonecutterRecipe; + +import static com.refinedmods.refinedstorage.common.autocrafting.PatternGridScreen.INSET_PADDING; +import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createIdentifier; +import static java.util.Objects.requireNonNull; + +class StonecutterPatternGridRenderer implements PatternGridRenderer { + private static final ResourceLocation SPRITE = createIdentifier("pattern_grid/stonecutter"); + + @Nullable + private ScrollbarWidget scrollbar; + + private final PatternGridContainerMenu menu; + private final int leftPos; + private final int x; + private final int y; + + StonecutterPatternGridRenderer(final PatternGridContainerMenu menu, final int leftPos, final int x, final int y) { + this.menu = menu; + this.leftPos = leftPos; + this.x = x; + this.y = y; + } + + @Override + public void addWidgets(final Consumer widgets, + final Consumer renderables) { + scrollbar = createStonecutterScrollbar(menu, x, y); + updateScrollbarMaxOffset(); + widgets.accept(scrollbar); + } + + private static ScrollbarWidget createStonecutterScrollbar(final PatternGridContainerMenu menu, + final int x, + final int y) { + final ScrollbarWidget scrollbar = new ScrollbarWidget( + x + 107, + y + 9, + ScrollbarWidget.Type.NORMAL, + 54 + ); + scrollbar.visible = isScrollbarVisible(menu); + return scrollbar; + } + + private void updateScrollbarMaxOffset() { + if (scrollbar == null) { + return; + } + final int items = menu.getStonecutterRecipes().size(); + final int rows = Math.ceilDiv(items, VanillaConstants.STONECUTTER_RECIPES_PER_ROW); + final int maxOffset = rows - VanillaConstants.STONECUTTER_ROWS_VISIBLE; + final int maxOffsetCorrected = maxOffset * (scrollbar.isSmoothScrolling() ? 18 : 1); + scrollbar.setMaxOffset(maxOffsetCorrected); + scrollbar.setEnabled(maxOffsetCorrected > 0); + } + + @Override + public void tick() { + updateScrollbarMaxOffset(); + } + + @Override + public void render(final GuiGraphics graphics, + final int mouseX, + final int mouseY, + final float partialTicks) { + if (scrollbar != null) { + scrollbar.render(graphics, mouseX, mouseY, partialTicks); + } + } + + @Override + public int getClearButtonX() { + return leftPos + 130; + } + + @Override + public int getClearButtonY() { + return y + 8; + } + + @Override + public void renderBackground(final GuiGraphics graphics, + final float partialTicks, + final int mouseX, + final int mouseY) { + graphics.blitSprite(SPRITE, x + INSET_PADDING, y + INSET_PADDING + 4, 116, 56); + graphics.enableScissor(x + 40, y + 9, x + 40 + 64, y + 9 + 54); + final boolean isOverArea = isOverStonecutterArea(mouseX, mouseY); + for (int i = 0; i < menu.getStonecutterRecipes().size(); ++i) { + final RecipeHolder recipe = menu.getStonecutterRecipes().get(i); + final int xx = getRecipeX(x, i); + final int row = i / VanillaConstants.STONECUTTER_RECIPES_PER_ROW; + final int yy = getRecipeY(y, row); + if (yy < y + 9 - 18 || yy > y + 9 + 54) { + continue; + } + final boolean hovering = mouseX >= xx && mouseY >= yy && mouseX < xx + 16 && mouseY < yy + 18; + final ResourceLocation buttonSprite; + if (i == menu.getStonecutterSelectedRecipe()) { + buttonSprite = VanillaConstants.STONECUTTER_RECIPE_SELECTED_SPRITE; + } else if (isOverArea && hovering) { + buttonSprite = VanillaConstants.STONECUTTER_RECIPE_HIGHLIGHTED_SPRITE; + } else { + buttonSprite = VanillaConstants.STONECUTTER_RECIPE_SPRITE; + } + graphics.blitSprite(buttonSprite, xx, yy, 16, 18); + graphics.renderItem( + recipe.value().getResultItem(requireNonNull(PlatformUtil.getClientLevel()).registryAccess()), + xx, + yy + 1 + ); + } + graphics.disableScissor(); + } + + @Override + public void renderTooltip(final Font font, + @Nullable final Slot hoveredSlot, + final GuiGraphics graphics, + final int mouseX, + final int mouseY) { + if (!isOverStonecutterArea(mouseX, mouseY)) { + return; + } + for (int i = 0; i < menu.getStonecutterRecipes().size(); ++i) { + final RecipeHolder recipe = menu.getStonecutterRecipes().get(i); + final ItemStack result = recipe.value().getResultItem( + requireNonNull(PlatformUtil.getClientLevel()).registryAccess() + ); + final int xx = getRecipeX(x, i); + final int row = i / VanillaConstants.STONECUTTER_RECIPES_PER_ROW; + final int yy = getRecipeY(y, row); + if (yy < y + 9 - 18 || yy > y + 9 + 54) { + continue; + } + if (mouseX >= xx && mouseY >= yy && mouseX < xx + 16 && mouseY < yy + 18) { + graphics.renderTooltip(font, result, mouseX, mouseY); + } + } + } + + @Override + public boolean mouseClicked(final double mouseX, final double mouseY, final int clickedButton) { + return (scrollbar != null && scrollbar.mouseClicked(mouseX, mouseY, clickedButton)) + || clickedRecipe(mouseX, mouseY); + } + + @Override + public void mouseMoved(final double mouseX, final double mouseY) { + if (scrollbar != null) { + scrollbar.mouseMoved(mouseX, mouseY); + } + } + + @Override + public boolean mouseReleased(final double mouseX, final double mouseY, final int button) { + return scrollbar != null && scrollbar.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseScrolled(final double mouseX, + final double mouseY, + final double mouseZ, + final double delta) { + return isOverStonecutterArea(mouseX, mouseY) + && scrollbar != null + && scrollbar.isActive() + && scrollbar.mouseScrolled(mouseX, mouseY, mouseZ, delta); + } + + @Override + public void patternTypeChanged(final PatternType newPatternType) { + if (scrollbar != null) { + scrollbar.visible = isScrollbarVisible(menu); + } + } + + private static boolean isScrollbarVisible(final PatternGridContainerMenu menu) { + return menu.getPatternType() == PatternType.STONECUTTER; + } + + private boolean clickedRecipe(final double mouseX, + final double mouseY) { + if (!isOverStonecutterArea(mouseX, mouseY)) { + return false; + } + for (int i = 0; i < menu.getStonecutterRecipes().size(); ++i) { + final int xx = getRecipeX(x, i); + final int row = i / VanillaConstants.STONECUTTER_RECIPES_PER_ROW; + final int yy = getRecipeY(y, row); + if (yy < y + 9 - 18 || yy > y + 9 + 54) { + continue; + } + if (mouseX >= xx && mouseY >= yy && mouseX < xx + 16 && mouseY < yy + 18) { + menu.setStonecutterSelectedRecipe(i); + Minecraft.getInstance().getSoundManager().play( + SimpleSoundInstance.forUI(SoundEvents.UI_STONECUTTER_SELECT_RECIPE, 1.0F) + ); + return true; + } + } + return false; + } + + private boolean isOverStonecutterArea(final double mouseX, final double mouseY) { + return mouseX >= x + 40 + && (mouseX < x + 40 + 81) + && mouseY > y + 8 + && (mouseY < y + 8 + 56); + } + + private int getRecipeX(final int insetX, final int i) { + return insetX + 40 + i % VanillaConstants.STONECUTTER_RECIPES_PER_ROW * 16; + } + + private int getRecipeY(final int insetY, final int row) { + return insetY + + 9 + + (row * 18) + - ((scrollbar != null ? (int) scrollbar.getOffset() : 0) + * (scrollbar != null && scrollbar.isSmoothScrolling() ? 1 : 18)); + } +} diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/screen/AbstractGridScreen.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/screen/AbstractGridScreen.java index 768a3f9b8..27556d7d2 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/screen/AbstractGridScreen.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/screen/AbstractGridScreen.java @@ -12,6 +12,7 @@ import com.refinedmods.refinedstorage.common.grid.AbstractGridContainerMenu; import com.refinedmods.refinedstorage.common.grid.NoopGridSynchronizer; import com.refinedmods.refinedstorage.common.grid.view.ItemGridResource; +import com.refinedmods.refinedstorage.common.support.ResourceSlotRendering; import com.refinedmods.refinedstorage.common.support.TextureIds; import com.refinedmods.refinedstorage.common.support.containermenu.DisabledSlot; import com.refinedmods.refinedstorage.common.support.containermenu.PropertyTypes; @@ -297,7 +298,7 @@ private void renderAmount(final GuiGraphics graphics, : requireNonNullElse(ChatFormatting.WHITE.getColor(), 15); final boolean large = (minecraft != null && minecraft.isEnforceUnicode()) || Platform.INSTANCE.getConfig().getGrid().isLargeFont(); - renderAmount(graphics, slotX, slotY, text, color, large); + ResourceSlotRendering.renderAmount(graphics, slotX, slotY, text, color, large); } private void renderDisabledSlot(final GuiGraphics graphics, final int slotX, final int slotY) { diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/AbstractBaseScreen.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/AbstractBaseScreen.java index 6d67311ce..5cf47b3a0 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/AbstractBaseScreen.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/AbstractBaseScreen.java @@ -5,7 +5,6 @@ import com.refinedmods.refinedstorage.common.api.RefinedStorageApi; import com.refinedmods.refinedstorage.common.api.support.resource.PlatformResourceKey; import com.refinedmods.refinedstorage.common.api.support.resource.ResourceFactory; -import com.refinedmods.refinedstorage.common.api.support.resource.ResourceRendering; import com.refinedmods.refinedstorage.common.api.upgrade.UpgradeMapping; import com.refinedmods.refinedstorage.common.support.amount.ResourceAmountScreen; import com.refinedmods.refinedstorage.common.support.containermenu.AbstractResourceContainerMenu; @@ -23,10 +22,6 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; @@ -40,7 +35,6 @@ import org.apiguardian.api.API; import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createTranslationAsHeading; -import static java.util.Objects.requireNonNullElse; public abstract class AbstractBaseScreen extends AbstractContainerScreen { private static final SmallTextClientTooltipComponent CLICK_TO_CLEAR = new SmallTextClientTooltipComponent( @@ -110,71 +104,10 @@ protected void renderResourceSlots(final GuiGraphics graphics) { return; } for (final ResourceSlot slot : resourceContainerMenu.getResourceSlots()) { - tryRenderResourceSlot(graphics, slot); + ResourceSlotRendering.render(graphics, slot, leftPos, topPos); } } - protected final void tryRenderResourceSlot(final GuiGraphics graphics, final ResourceSlot slot) { - final ResourceKey resource = slot.getResource(); - if (resource == null) { - return; - } - renderResourceSlot( - graphics, - leftPos + slot.x, - topPos + slot.y, - resource, - slot.getAmount(), - slot.shouldRenderAmount() - ); - } - - private void renderResourceSlot(final GuiGraphics graphics, - final int x, - final int y, - final ResourceKey resource, - final long amount, - final boolean renderAmount) { - final ResourceRendering rendering = RefinedStorageApi.INSTANCE.getResourceRendering(resource); - rendering.render(resource, graphics, x, y); - if (renderAmount) { - renderResourceAmount(graphics, x, y, amount, rendering); - } - } - - public static void renderResourceAmount(final GuiGraphics graphics, - final int x, - final int y, - final long amount, - final ResourceRendering rendering) { - renderAmount( - graphics, - x, - y, - rendering.getDisplayedAmount(amount, true), - requireNonNullElse(ChatFormatting.WHITE.getColor(), 15), - true - ); - } - - protected static void renderAmount(final GuiGraphics graphics, - final int x, - final int y, - final String amount, - final int color, - final boolean large) { - final Font font = Minecraft.getInstance().font; - final PoseStack poseStack = graphics.pose(); - poseStack.pushPose(); - // Large amounts overlap with the slot lines (see Minecraft behavior) - poseStack.translate(x + (large ? 1D : 0D), y + (large ? 1D : 0D), 199); - if (!large) { - poseStack.scale(0.5F, 0.5F, 1); - } - graphics.drawString(font, amount, (large ? 16 : 30) - font.width(amount), large ? 8 : 22, color, true); - poseStack.popPose(); - } - public void addSideButton(final AbstractSideButtonWidget button) { button.setX(leftPos - button.getWidth() - 2); button.setY(topPos + sideButtonY); diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/ResourceSlotRendering.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/ResourceSlotRendering.java new file mode 100644 index 000000000..f351c64c3 --- /dev/null +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/ResourceSlotRendering.java @@ -0,0 +1,83 @@ +package com.refinedmods.refinedstorage.common.support; + +import com.refinedmods.refinedstorage.api.resource.ResourceKey; +import com.refinedmods.refinedstorage.common.api.RefinedStorageApi; +import com.refinedmods.refinedstorage.common.api.support.resource.ResourceRendering; +import com.refinedmods.refinedstorage.common.support.containermenu.ResourceSlot; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; + +import static java.util.Objects.requireNonNullElse; + +public final class ResourceSlotRendering { + private ResourceSlotRendering() { + } + + public static void render(final GuiGraphics graphics, + final ResourceSlot slot, + final int leftPos, + final int topPos) { + final ResourceKey resource = slot.getResource(); + if (resource == null) { + return; + } + render( + graphics, + leftPos + slot.x, + topPos + slot.y, + resource, + slot.getAmount(), + slot.shouldRenderAmount() + ); + } + + private static void render(final GuiGraphics graphics, + final int x, + final int y, + final ResourceKey resource, + final long amount, + final boolean renderAmount) { + final ResourceRendering rendering = RefinedStorageApi.INSTANCE.getResourceRendering(resource); + rendering.render(resource, graphics, x, y); + if (renderAmount) { + render(graphics, x, y, amount, rendering); + } + } + + public static void render(final GuiGraphics graphics, + final int x, + final int y, + final long amount, + final ResourceRendering rendering) { + renderAmount( + graphics, + x, + y, + rendering.getDisplayedAmount(amount, true), + requireNonNullElse(ChatFormatting.WHITE.getColor(), 15), + true + ); + } + + public static void renderAmount(final GuiGraphics graphics, + final int x, + final int y, + final String amount, + final int color, + final boolean large) { + final Font font = Minecraft.getInstance().font; + final PoseStack poseStack = graphics.pose(); + poseStack.pushPose(); + // Large amounts overlap with the slot lines (see Minecraft behavior) + poseStack.translate(x + (large ? 1D : 0D), y + (large ? 1D : 0D), 199); + if (!large) { + poseStack.scale(0.5F, 0.5F, 1); + } + graphics.drawString(font, amount, (large ? 16 : 30) - font.width(amount), large ? 8 : 22, color, true); + poseStack.popPose(); + } +} diff --git a/refinedstorage-common/src/main/resources/assets/refinedstorage/textures/gui/sprites/pattern_grid/stonecutter.png b/refinedstorage-common/src/main/resources/assets/refinedstorage/textures/gui/sprites/pattern_grid/stonecutter.png index 6d57f51bf..5cc63d88a 100644 Binary files a/refinedstorage-common/src/main/resources/assets/refinedstorage/textures/gui/sprites/pattern_grid/stonecutter.png and b/refinedstorage-common/src/main/resources/assets/refinedstorage/textures/gui/sprites/pattern_grid/stonecutter.png differ