diff options
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java')
-rw-r--r-- | src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java new file mode 100644 index 00000000..d47fef05 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/AuctionBrowserScreen.java @@ -0,0 +1,388 @@ +package de.hysky.skyblocker.skyblock.auction; + +import com.google.gson.JsonElement; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.auction.widgets.AuctionTypeWidget; +import de.hysky.skyblocker.skyblock.auction.widgets.CategoryTabWidget; +import de.hysky.skyblocker.skyblock.auction.widgets.RarityWidget; +import de.hysky.skyblocker.skyblock.auction.widgets.SortWidget; +import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip; +import de.hysky.skyblocker.skyblock.item.tooltip.TooltipInfoType; +import de.hysky.skyblocker.utils.ItemUtils; +import de.hysky.skyblocker.utils.render.gui.AbstractCustomHypixelGUI; +import it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Colors; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +public class AuctionBrowserScreen extends AbstractCustomHypixelGUI<AuctionHouseScreenHandler> { + private static final Logger LOGGER = LoggerFactory.getLogger(AuctionBrowserScreen.class); + private static final Identifier TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/auctions_gui/browser/background.png"); + private static final Identifier SCROLLER_TEXTURE = new Identifier("container/creative_inventory/scroller"); + + private static final Identifier up_arrow_tex = new Identifier(SkyblockerMod.NAMESPACE, "up_arrow_even"); // Put them in their own fields to avoid object allocation on each frame + private static final Identifier down_arrow_tex = new Identifier(SkyblockerMod.NAMESPACE, "down_arrow_even"); + public static final Supplier<Sprite> UP_ARROW = () -> MinecraftClient.getInstance().getGuiAtlasManager().getSprite(up_arrow_tex); + public static final Supplier<Sprite> DOWN_ARROW = () -> MinecraftClient.getInstance().getGuiAtlasManager().getSprite(down_arrow_tex); + + + // SLOTS + public static final int RESET_BUTTON_SLOT = 47; + public static final int SEARCH_BUTTON_SLOT = 48; + public static final int BACK_BUTTON_SLOT = 49; + public static final int SORT_BUTTON_SLOT = 50; + public static final int RARITY_BUTTON_SLOT = 51; + public static final int AUCTION_TYPE_BUTTON_SLOT = 52; + + public static final int PREV_PAGE_BUTTON = 46; + public static final int NEXT_PAGE_BUTTON = 53; + + private final Int2BooleanOpenHashMap isSlotHighlighted = new Int2BooleanOpenHashMap(24); + + + // WIDGETS + private SortWidget sortWidget; + private AuctionTypeWidget auctionTypeWidget; + private RarityWidget rarityWidget; + private ButtonWidget resetFiltersButton; + private final List<CategoryTabWidget> categoryTabWidgets = new ArrayList<>(6); + private String search = ""; + + public AuctionBrowserScreen(AuctionHouseScreenHandler handler, PlayerInventory inventory) { + super(handler, inventory, Text.literal("Auctions Browser")); + this.backgroundHeight = 187; + this.playerInventoryTitleY = 92; + this.titleX = 999; + } + + @Override + protected void init() { + super.init(); + sortWidget = new SortWidget(x + 25, y + 81, this::clickSlot); + sortWidget.setSlotId(SORT_BUTTON_SLOT); + addDrawableChild(sortWidget); + auctionTypeWidget = new AuctionTypeWidget(x + 134, y + 77, this::clickSlot); + auctionTypeWidget.setSlotId(AUCTION_TYPE_BUTTON_SLOT); + addDrawableChild(auctionTypeWidget); + rarityWidget = new RarityWidget(x + 73, y + 80, this::clickSlot); + rarityWidget.setSlotId(RARITY_BUTTON_SLOT); + addDrawableChild(rarityWidget); + resetFiltersButton = new ScaledTextButtonWidget(x + 10, y + 77, 12, 12, Text.literal("↻"), this::onResetPressed); + addDrawableChild(resetFiltersButton); + resetFiltersButton.setTooltip(Tooltip.of(Text.literal("Reset Filters"))); + resetFiltersButton.setTooltipDelay(500); + + addDrawableChild(new ButtonWidget.Builder(Text.literal("<"), button -> this.clickSlot(BACK_BUTTON_SLOT)) + .position(x + 98, y + 4) + .size(12, 12) + .build()); + + if (categoryTabWidgets.isEmpty()) + for (int i = 0; i < 6; i++) { + CategoryTabWidget categoryTabWidget = new CategoryTabWidget(new ItemStack(Items.SPONGE), this::clickSlot); + categoryTabWidgets.add(categoryTabWidget); + addSelectableChild(categoryTabWidget); // This method only makes it clickable, does not add it to the drawables list + // manually rendered in the render method to have it not render behind the durability bars + categoryTabWidget.setPosition(x - 30, y + 3 + i * 28); + } + else + for (int i = 0; i < categoryTabWidgets.size(); i++) { + CategoryTabWidget categoryTabWidget = categoryTabWidgets.get(i); + categoryTabWidget.setPosition(x - 30, y + 3 + i * 28); + + } + } + + private void onResetPressed(ButtonWidget buttonWidget) { + buttonWidget.setFocused(false); // Annoying. + this.clickSlot(RESET_BUTTON_SLOT, 0); + } + + @Override + protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) { + context.drawTexture(TEXTURE, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight); + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + super.render(context, mouseX, mouseY, delta); + for (CategoryTabWidget categoryTabWidget : categoryTabWidgets) { + categoryTabWidget.render(context, mouseX, mouseY, delta); + } + if (isWaitingForServer) { + String waiting = "Waiting for server..."; + context.drawText(textRenderer, waiting, this.width - textRenderer.getWidth(waiting) - 5, this.height - textRenderer.fontHeight - 2, Colors.WHITE, true); + } + + MatrixStack matrices = context.getMatrices(); + matrices.push(); + matrices.translate(x, y, 0); + // Search + context.enableScissor(x + 7, y + 4, x + 97, y + 16); + context.drawText(textRenderer, Text.literal(search).fillStyle(Style.EMPTY.withUnderline(onSearchField(mouseX, mouseY))), 9, 6, Colors.WHITE, true); + context.disableScissor(); + + // Scrollbar + if (prevPageVisible) { + if (onScrollbarTop(mouseX, mouseY)) + context.drawSprite(159, 13, 0, 6, 3, UP_ARROW.get()); + else context.drawSprite(159, 13, 0, 6, 3, UP_ARROW.get(), 0.54f, 0.54f, 0.54f, 1); + } + + if (nextPageVisible) { + if (onScrollbarBottom(mouseX, mouseY)) + context.drawSprite(159, 72, 0, 6, 3, DOWN_ARROW.get()); + else context.drawSprite(159, 72, 0, 6, 3, DOWN_ARROW.get(), 0.54f, 0.54f, 0.54f, 1); + } + context.drawText(textRenderer, String.format("%d/%d", currentPage, totalPages), 111, 6, Colors.GRAY, false); + if (totalPages <= 1) + context.drawGuiTexture(SCROLLER_TEXTURE, 156, 18, 12, 15); + else + context.drawGuiTexture(SCROLLER_TEXTURE, 156, (int) (18 + (float) (Math.min(currentPage, totalPages) - 1) / (totalPages - 1) * 37), 12, 15); + + matrices.pop(); + + this.drawMouseoverTooltip(context, mouseX, mouseY); + } + + @Override + protected void drawSlot(DrawContext context, Slot slot) { + if (SkyblockerConfigManager.get().general.fancyAuctionHouse.highlightCheapBIN && isSlotHighlighted.getOrDefault(slot.id, false)) { + context.drawBorder(slot.x, slot.y, 16, 16, new Color(0, 255, 0, 100).getRGB()); + } + super.drawSlot(context, slot); + } + + @Override + protected void onMouseClick(Slot slot, int slotId, int button, SlotActionType actionType) { + if (slotId >= handler.getRows() * 9) return; + super.onMouseClick(slot, slotId, button, actionType); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (isWaitingForServer) return super.mouseClicked(mouseX, mouseY, button); + if (onScrollbarTop((int) mouseX, (int) mouseY) && prevPageVisible) { + clickSlot(PREV_PAGE_BUTTON); + return true; + } + if (onScrollbarBottom((int) mouseX, (int) mouseY) && nextPageVisible) { + clickSlot(NEXT_PAGE_BUTTON); + return true; + } + + if (onSearchField((int) mouseX, (int) mouseY)) { + clickSlot(SEARCH_BUTTON_SLOT); + return true; + } + return super.mouseClicked(mouseX, mouseY, button); + } + + private boolean onScrollbarTop(int mouseX, int mouseY) { + int localX = mouseX - x; + int localY = mouseY - y; + return localX > 154 && localX < 169 && localY > 6 && localY < 44; + } + + private boolean onScrollbarBottom(int mouseX, int mouseY) { + int localX = mouseX - x; + int localY = mouseY - y; + return localX > 154 && localX < 169 && localY > 43 && localY < 80; + } + + private boolean onSearchField(int mouseX, int mouseY) { + int localX = mouseX - x; + int localY = mouseY - y; + return localX > 6 && localX < 97 && localY > 3 && localY < 16; + } + + @Override + public void onSlotChange(AuctionHouseScreenHandler handler, int slotId, ItemStack stack) { + if (client == null || stack.isEmpty()) return; + isWaitingForServer = false; + + switch (slotId) { + case PREV_PAGE_BUTTON -> { + prevPageVisible = false; + if (stack.isOf(Items.ARROW)) { + prevPageVisible = true; + parsePage(stack); + } + } + case NEXT_PAGE_BUTTON -> { + nextPageVisible = false; + if (stack.isOf(Items.ARROW)) { + nextPageVisible = true; + parsePage(stack); + } + } + case SORT_BUTTON_SLOT -> + sortWidget.setCurrent(SortWidget.Option.get(getOrdinal(ItemUtils.getNbtTooltips(stack)))); + case AUCTION_TYPE_BUTTON_SLOT -> + auctionTypeWidget.setCurrent(AuctionTypeWidget.Option.get(getOrdinal(ItemUtils.getNbtTooltips(stack)))); + case RARITY_BUTTON_SLOT -> { + List<Text> tooltip = ItemUtils.getNbtTooltips(stack); + int ordinal = getOrdinal(tooltip); + String split = tooltip.get(ordinal + 1).getString().substring(2); + rarityWidget.setText(tooltip.subList(1, tooltip.size() - 3), split); + } + case RESET_BUTTON_SLOT -> { + if (resetFiltersButton != null) + resetFiltersButton.active = handler.getSlot(slotId).getStack().isOf(Items.ANVIL); + } + case SEARCH_BUTTON_SLOT -> { + List<Text> tooltipSearch = ItemUtils.getNbtTooltips(stack); + for (Text text : tooltipSearch) { + String string = text.getString(); + if (string.contains("Filtered:")) { + String[] splitSearch = string.split(":"); + if (splitSearch.length < 2) { + search = ""; + } else search = splitSearch[1].trim(); + break; + } + } + } + default -> { + if (slotId < this.handler.getRows() * 9 && slotId % 9 == 0) { + CategoryTabWidget categoryTabWidget = categoryTabWidgets.get(slotId / 9); + categoryTabWidget.setSlotId(slotId); + categoryTabWidget.setIcon(handler.getSlot(slotId).getStack()); + List<Text> tooltipDefault = ItemUtils.getNbtTooltips(handler.getSlot(slotId).getStack()); + for (int j = tooltipDefault.size() - 1; j >= 0; j--) { + String lowerCase = tooltipDefault.get(j).getString().toLowerCase(); + if (lowerCase.contains("currently")) { + categoryTabWidget.setToggled(true); + break; + } else if (lowerCase.contains("click")) { + categoryTabWidget.setToggled(false); + break; + } else categoryTabWidget.setToggled(false); + } + } else if (slotId > 9 && slotId < (handler.getRows() - 1) * 9 && slotId % 9 > 1 && slotId % 9 < 8) { + if (!SkyblockerConfigManager.get().general.fancyAuctionHouse.highlightCheapBIN) return; + List<Text> tooltip = ItemUtils.getNbtTooltips(stack); + for (int k = tooltip.size() - 1; k >= 0; k--) { + Text text = tooltip.get(k); + String string = text.getString(); + if (string.toLowerCase().contains("buy it now:")) { + String[] split = string.split(":"); + if (split.length < 2) continue; + String coins = split[1].replace(",", "").replace("coins", "").trim(); + try { + long parsed = Long.parseLong(coins); + String name = ItemTooltip.getInternalNameFromNBT(stack, false); + String internalID = ItemTooltip.getInternalNameFromNBT(stack, true); + String neuName = name; + if (name == null || internalID == null) break; + if (name.startsWith("ISSHINY_")) { + neuName = internalID; + } + JsonElement jsonElement = TooltipInfoType.THREE_DAY_AVERAGE.getData().get(ItemTooltip.getNeuName(internalID, neuName)); + if (jsonElement == null) break; + else { + isSlotHighlighted.put(slotId, jsonElement.getAsDouble() > parsed); + } + } catch (Exception e) { + LOGGER.error("[Skyblocker Fancy Auction House] Failed to parse BIN price", e); + } + } + } + } + } + } + } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (keyCode == GLFW.GLFW_KEY_UP && prevPageVisible) { + clickSlot(PREV_PAGE_BUTTON); + return true; + } + if (keyCode == GLFW.GLFW_KEY_DOWN && nextPageVisible) { + clickSlot(NEXT_PAGE_BUTTON); + return true; + } + return super.keyPressed(keyCode, scanCode, modifiers); + } + + private static int getOrdinal(List<Text> tooltip) { + int ordinal = 0; + for (int j = 0; j < tooltip.size() - 4; j++) { + if (j + 1 >= tooltip.size()) break; + if (tooltip.get(j + 1).getString().contains("▶")) { + ordinal = j; + break; + } + } + return ordinal; + } + + int currentPage = 0; + int totalPages = 1; + private boolean prevPageVisible = false; + private boolean nextPageVisible = false; + + private void parsePage(ItemStack stack) { + assert client != null; + try { + List<Text> tooltip = ItemUtils.getNbtTooltips(stack); + String str = tooltip.get(0).getString().trim(); + str = str.substring(1, str.length() - 1); // remove parentheses + String[] parts = str.split("/"); // split the string + currentPage = Integer.parseInt(parts[0].replace(",", "")); // parse current page + totalPages = Integer.parseInt(parts[1].replace(",", "")); // parse total + } catch (Exception e) { + LOGGER.error("[Skyblocker Fancy Auction House] Failed to parse page arrow", e); + } + } + + @Override + protected boolean isClickOutsideBounds(double mouseX, double mouseY, int left, int top, int button) { + return mouseX < (double) left - 32 || mouseY < (double) top || mouseX >= (double) (left + this.backgroundWidth) || mouseY >= (double) (top + this.backgroundHeight); + } + + private static class ScaledTextButtonWidget extends ButtonWidget { + + protected ScaledTextButtonWidget(int x, int y, int width, int height, Text message, PressAction onPress) { + super(x, y, width, height, message, onPress, Supplier::get); + } + + // Code taken mostly from YACL by isxander. Love you <3 + @Override + public void drawMessage(DrawContext graphics, TextRenderer textRenderer, int color) { + TextRenderer font = MinecraftClient.getInstance().textRenderer; + MatrixStack pose = graphics.getMatrices(); + float textScale = 2.f; + + pose.push(); + pose.translate(((this.getX() + this.width / 2f) - font.getWidth(getMessage()) * textScale / 2) + 1, (float) this.getY() + (this.height - font.fontHeight * textScale) / 2f - 1, 0); + pose.scale(textScale, textScale, 1); + graphics.drawText(font, getMessage(), 0, 0, color | MathHelper.ceil(this.alpha * 255.0F) << 24, true); + pose.pop(); + } + } +} |