diff options
| author | vicisacat <victor.branchu@gmail.com> | 2024-01-12 18:11:35 +0100 |
|---|---|---|
| committer | vicisacat <victor.branchu@gmail.com> | 2024-01-12 18:11:35 +0100 |
| commit | 098b003a641225b97ffd05c12df3954db901397a (patch) | |
| tree | 4a71e2494dd3587093f8d4228af31db7c6f98a55 /src/main/java/de/hysky/skyblocker/skyblock | |
| parent | 2a597ea5d76835df1c00e7a944e5899b96bd5b0d (diff) | |
| download | Skyblocker-098b003a641225b97ffd05c12df3954db901397a.tar.gz Skyblocker-098b003a641225b97ffd05c12df3954db901397a.tar.bz2 Skyblocker-098b003a641225b97ffd05c12df3954db901397a.zip | |
Adds a custom GUI for the Party Finder in dungeons. Is it good? Debatable.
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock')
6 files changed, 1537 insertions, 0 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/FinderSettingsContainer.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/FinderSettingsContainer.java new file mode 100644 index 00000000..18cebff7 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/FinderSettingsContainer.java @@ -0,0 +1,282 @@ +package de.hysky.skyblocker.skyblock.dungeon.partyfinder; + +import net.minecraft.block.entity.SignBlockEntity; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.widget.ContainerWidget; +import net.minecraft.client.item.TooltipContext; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.screen.GenericContainerScreenHandler; +import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; + +import java.util.ArrayList; +import java.util.List; + +public class FinderSettingsContainer extends ContainerWidget{ + + private boolean isInitialized = false; + private OptionDropdownWidget floorSelector; + private OptionDropdownWidget dungeonTypeSelector; + private OptionDropdownWidget sortGroupsSelector; + + private RangedValueWidget classLevelRange; + private RangedValueWidget dungeonLevelRange; + + private ContainerWidget currentlyOpenedOption = null; + + private final List<ContainerWidget> initializedWidgets = new ArrayList<>(); + + + public FinderSettingsContainer(int x, int y, int height) { + super(x, y, 336, height, Text.empty()); + } + + @Override + public void setDimensionsAndPosition(int width, int height, int x, int y) { + super.setDimensionsAndPosition(width, height, x, y); + if (this.floorSelector != null) floorSelector.setPosition(x + width/4-70, y + 20); + if (this.dungeonTypeSelector != null) dungeonTypeSelector.setPosition(x + 3*width/4-70, y + 20); + if (this.sortGroupsSelector != null) sortGroupsSelector.setPosition(x + width/2-70, y + 120); + if (this.classLevelRange != null) classLevelRange.setPosition(x + width/4-50, y + 70); + if (this.dungeonLevelRange != null) dungeonLevelRange.setPosition(x + 3*width/4-50, y + 70); + + } + + /** + * Handles everything in the Settings page + * @param screen the parent Party Finder screen + * @param inventoryName le inventory name + * @return returns false if it doesn't know what's happening + */ + public boolean handle(PartyFinderScreen screen, String inventoryName) { + String nameLowerCase = inventoryName.toLowerCase(); + GenericContainerScreenHandler handler = screen.getHandler(); + if (!isInitialized) { + if (!nameLowerCase.contains("search settings")) return false; + isInitialized = true; + //System.out.println("initializing"); + for (Slot slot : handler.slots) { + if (slot.id > handler.getRows() * 9) break; + if (!slot.hasStack()) continue; + ItemStack stack = slot.getStack(); + //System.out.println(stack.toString()); + String name = stack.getName().getString().toLowerCase(); + if (name.contains("floor")) { + + //System.out.println("Floor selector created"); + this.floorSelector = new OptionDropdownWidget(screen, stack.getName(), null, getX() + getWidth()/4-70, getY() + 20, 140, 170, slot.id); + if (!setSelectedElementFromTooltip(slot, stack, floorSelector)) return false; + + initializedWidgets.add(floorSelector); + + } else if (name.contains("dungeon type")) { + + this.dungeonTypeSelector = new OptionDropdownWidget(screen, stack.getName(), null, getX() + (3*getWidth())/4-70, getY() + 20, 140, 100, slot.id); + if (!setSelectedElementFromTooltip(slot, stack, dungeonTypeSelector)) return false; + + initializedWidgets.add(dungeonTypeSelector); + + } else if (name.contains("groups")) { + + this.sortGroupsSelector = new OptionDropdownWidget(screen, stack.getName(), null, getX() + getWidth()/2-70, getY() + 120, 140, 100, slot.id); + if (!setSelectedElementFromTooltip(slot, stack, sortGroupsSelector)) return false; + + initializedWidgets.add(sortGroupsSelector); + + } else if (name.contains("class level")) { + + this.classLevelRange = new RangedValueWidget(screen, stack.getName(), getX() + getWidth()/4-50, getY() + 70, 100, slot.id); + if (!setRangeFromTooltip(stack, classLevelRange)) return false; + + initializedWidgets.add(classLevelRange); + + } else if (name.contains("dungeon level")) { + + this.dungeonLevelRange = new RangedValueWidget(screen, stack.getName(), getX() + 3*(getWidth())/4-50, getY() + 70, 100, slot.id); + if (!setRangeFromTooltip(stack, dungeonLevelRange)) return false; + + initializedWidgets.add(dungeonLevelRange); + + } + } + } + if (nameLowerCase.contains("search settings")) { + if (floorSelector != null) floorSelector.close(); + if (dungeonTypeSelector != null) dungeonTypeSelector.close(); + if (sortGroupsSelector != null) sortGroupsSelector.close(); + if (classLevelRange != null) classLevelRange.setState(RangedValueWidget.State.CLOSED); + if (dungeonLevelRange != null) dungeonLevelRange.setState(RangedValueWidget.State.CLOSED); + + screen.partyFinderButton.active = true; + currentlyOpenedOption = null; + + for (int i = (handler.getRows() - 1) * 9; i < handler.getRows() * 9; i++) { + Slot slot = handler.slots.get(i); + if (slot.hasStack() && slot.getStack().isOf(Items.ARROW)) { + screen.partyButtonSlotId = slot.id; + } + } + return true; + } else { + screen.partyFinderButton.active = false; + + if (nameLowerCase.contains("floor")) { + updateDropdownOptionWidget(handler, floorSelector); + currentlyOpenedOption = floorSelector; + return true; + } else if (nameLowerCase.contains("select type")) { + updateDropdownOptionWidget(handler, dungeonTypeSelector); + currentlyOpenedOption = dungeonTypeSelector; + return true; + } else if (nameLowerCase.contains("class level range")) { + updateRangedValue(handler, classLevelRange); + return true; + } else if (nameLowerCase.contains("dungeon level range")) { + updateRangedValue(handler, dungeonLevelRange); + return true; + } else if (nameLowerCase.contains("sort")) { + updateDropdownOptionWidget(handler, sortGroupsSelector); + currentlyOpenedOption = sortGroupsSelector; + return true; + } + } + return false; + } + + private int findBackSlotId(GenericContainerScreenHandler handler) { + int backId = -1; + for (int i = (handler.getRows() - 1) * 9; i < handler.getRows() * 9; i++) { + Slot slot = handler.slots.get(i); + if (slot.hasStack() && slot.getStack().isOf(Items.ARROW)) { + backId = slot.id; + break; + } + } + return backId; + } + + /** + * @return true if all goes well + */ + private boolean setRangeFromTooltip(ItemStack stack, RangedValueWidget widget) { + for (Text text : stack.getTooltip(null, TooltipContext.BASIC)) { + String textLowerCase = text.getString().toLowerCase(); + if (textLowerCase.contains("selected:")) { + String[] split = text.getString().split(":"); + if (split.length < 2) return false; + String[] minAndMax = split[1].split("-"); + if (minAndMax.length < 2) return false; + //System.out.println(textLowerCase); + //System.out.println("Min and max: " + minAndMax[0] + " " + minAndMax[1]); + int leMin = -1; + int leMax = -1; + try {leMin = Integer.parseInt(minAndMax[0].trim());} catch (NumberFormatException ignored) {} + try {leMax = Integer.parseInt(minAndMax[1].trim());} catch (NumberFormatException ignored) {} + + widget.setMinAndMax(leMin, leMax); + return true; + } + } + return false; + } + /** + * @return true if all goes well + */ + private boolean setSelectedElementFromTooltip(Slot slot, ItemStack stack, OptionDropdownWidget dropdownWidget) { + for (Text text : stack.getTooltip(null, TooltipContext.BASIC)) { + String textLowerCase = text.getString().toLowerCase(); + if (textLowerCase.contains("selected:")) { + String[] split = text.getString().split(":"); + if (split.length < 2) return false; + String floorName = split[1].trim(); + dropdownWidget.setSelectedOption(dropdownWidget.new Option(floorName, stack, slot.id)); + return true; + } + } + return false; + } + + public boolean handleSign(SignBlockEntity sign, boolean front) { + if (!isInitialized) return false; + if (currentlyOpenedOption == classLevelRange) { + return updateValues(sign, front, classLevelRange); + } else if (currentlyOpenedOption == dungeonLevelRange) { + return updateValues(sign, front, dungeonLevelRange); + } + return false; + } + + private boolean updateValues(SignBlockEntity sign, boolean front, RangedValueWidget valueWidget) { + RangedValueWidget.State state; + String lowerCase = sign.getText(front).getMessage(3, false).getString().toLowerCase(); + if (lowerCase.contains("max")) { + state = RangedValueWidget.State.MODIFYING_MAX; + } else if (lowerCase.contains("min")) { + state = RangedValueWidget.State.MODIFYING_MIN; + } else return false; + valueWidget.setState(state); + this.setFocused(valueWidget); + return true; + } + + private void updateDropdownOptionWidget(GenericContainerScreenHandler handler, OptionDropdownWidget dropdownWidget) { + List<OptionDropdownWidget.Option> entries = new ArrayList<>(); + for (Slot slot : handler.slots) { + if (slot.id > (handler.getRows() - 1) * 9) break; + if (slot.hasStack() && !slot.getStack().isOf(Items.BLACK_STAINED_GLASS_PANE)) { + entries.add(dropdownWidget.new Option(slot.getStack().getName().getString(), slot.getStack(), slot.id)); + } + } + int backId = findBackSlotId(handler); + dropdownWidget.open(entries, backId); + } + + private void updateRangedValue(GenericContainerScreenHandler handler, RangedValueWidget valueWidget) { + currentlyOpenedOption = valueWidget; + int min = -1; + int max = -1; + for (Slot slot : handler.slots) { + if (slot.id > (handler.getRows() - 1) * 9) break; + if (slot.hasStack() && slot.getStack().getName().getString().toLowerCase().contains("min")) { + min = slot.id; + } else if (slot.hasStack() && slot.getStack().getName().getString().toLowerCase().contains("max")) { + max = slot.id; + } + } + int backId = findBackSlotId(handler); + + valueWidget.setStateAndSlots(RangedValueWidget.State.OPEN, min, max, backId); + } + + public void setVisible(boolean visible) { + this.visible = visible; + if (floorSelector != null) this.floorSelector.visible = visible; + if (dungeonTypeSelector != null) this.dungeonTypeSelector.visible = visible; + if (classLevelRange != null) this.classLevelRange.visible = visible; + if (dungeonLevelRange != null) this.dungeonLevelRange.visible = visible; + if (sortGroupsSelector != null) this.sortGroupsSelector.visible = visible; + } + + public boolean canInteract(ContainerWidget widget) { + return currentlyOpenedOption == null || currentlyOpenedOption == widget; + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (!visible) return; + for (ContainerWidget initializedWidget : initializedWidgets) { + initializedWidget.render(context, mouseX, mouseY, delta); + } + } + + @Override + public List<? extends Element> children() { + return initializedWidgets; + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) {} +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java new file mode 100644 index 00000000..ff15464b --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/OptionDropdownWidget.java @@ -0,0 +1,203 @@ +package de.hysky.skyblocker.skyblock.dungeon.partyfinder; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.Selectable; +import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class OptionDropdownWidget extends ElementListWidget<OptionDropdownWidget.Option> { + private final int slotId; + private int backButtonId = -1; + private final Text name; + private @Nullable Option selectedOption; + protected final PartyFinderScreen screen; + private boolean isOpen = false; + + private float animationProgress = 0f; + + public OptionDropdownWidget(PartyFinderScreen screen, Text name, @Nullable Option selectedOption, int x, int y, int width, int height, int slotId) { + super(screen.getClient(), width, height, y, 15); + this.screen = screen; + this.slotId = slotId; + setX(x); + setRenderBackground(false); + setRenderHeader(true, 25); + this.name = name; + this.selectedOption = selectedOption; + } + + @Override + protected boolean clickedHeader(int x, int y) { + if (!(x >= 0 && y >= 10 && x < getWidth() && y < 26)) return false; + if (screen.isWaitingForServer()) return false; + if (isOpen) { + if (backButtonId != -1) screen.clickAndWaitForServer(backButtonId); + } else { + screen.clickAndWaitForServer(slotId); + screen.partyFinderButton.active = false; + } + animationProgress = 0f; + return true; + } + + @Override + public int getRowLeft() { + return getX() + 2; + } + + @Override + protected int getScrollbarPositionX() { + return getRowLeft() + getRowWidth(); + } + + @Override + public int getRowWidth() { + return getWidth() - 6; + } + + public void setSelectedOption(@NotNull OptionDropdownWidget.Option entry) { + selectedOption = entry; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (!screen.getSettingsContainer().canInteract(this)) return false; + if (isOpen && !isMouseOver(mouseX, mouseY) && backButtonId != -1) { + screen.clickAndWaitForServer(backButtonId); + return true; + } + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (screen.getSettingsContainer().canInteract(this)) return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + return false; + } + + @Override + protected void renderHeader(DrawContext context, int x, int y) { + context.drawText(MinecraftClient.getInstance().textRenderer, name, x, y+1, 0xFFD0D0D0, false); + int offset = 10; + context.fill(x-2, y + offset, x - 3 + getWidth(), y + 15 + offset, 0xFFF0F0F0); + context.fill(x-1, y+1+offset, x-3 + getWidth()-1, y + 14 + offset, 0xFF000000); + if (selectedOption != null) { + context.drawText(MinecraftClient.getInstance().textRenderer, selectedOption.message, x+2, y+3+offset, 0xFFFFFFFF, true); + } + else context.drawText(MinecraftClient.getInstance().textRenderer, "???", x+2, y+3+offset, 0xFFFFFFFF, true); + } + + @Override + public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + MatrixStack matrices = context.getMatrices(); + if (isOpen) { + matrices.push(); + matrices.translate(0, 0, 100); + } + if (animationProgress < 1) animationProgress += delta * 0.5f;else if (animationProgress != 1) animationProgress = 1; + if (PartyFinderScreen.DEBUG) { + context.drawText(MinecraftClient.getInstance().textRenderer, String.valueOf(slotId), getX(), getY() - 10, 0xFFFF0000, true); + context.drawText(MinecraftClient.getInstance().textRenderer, String.valueOf(backButtonId), getX() + 50, getY() - 10, 0xFFFF0000, true); + } + + int height1 = Math.min(getHeight(), getEntryCount()*itemHeight+4); + int idk = isOpen ? (int) (height1 * animationProgress) : (int) (height1 * (1 - animationProgress)); + context.fill(getX(), getY() + headerHeight, getX() + getWidth()-1, getY() + idk + headerHeight, 0xFFE0E0E0); + context.fill(getX()+1, getY()+headerHeight+1, getX() + getWidth()-2, getY() + idk + headerHeight - 1, 0xFF000000); + + super.renderWidget(context, mouseX, mouseY, delta); + if (isOpen) { + matrices.pop(); + } + } + + public void open(List<Option> entries, int backButtonId) { + isOpen = true; + this.replaceEntries(entries); + animationProgress = 0f; + this.backButtonId = backButtonId; + } + + public void close() { + isOpen = false; + this.clearEntries(); + + } + + public class Option extends ElementListWidget.Entry<Option> { + + private final String message; + private final ItemStack icon; + private final int optionSlotId; + + public Option(@NotNull String message, @Nullable ItemStack icon, int slotId) { + + this.message = message; + this.icon = icon; + this.optionSlotId = slotId; + } + + + @Override + public List<? extends Selectable> selectableChildren() { + return List.of(); + } + + @Override + public List<? extends Element> children() { + return List.of(); + } + + @Override + public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + /*if (hovered) { + context.fill(x, y, x + entryWidth, y + 13, 0xFFF0F0F0); + context.fill(x+1, y+1, x + entryWidth-1, y + 12, 0xFF000000); + } else context.fill(x, y, x + entryWidth, y + 13, 0xFF000000);*/ + MatrixStack matrices = context.getMatrices(); + matrices.push(); + int iconY = y + 1; + matrices.translate(x, iconY, 0); + matrices.scale(0.8f, 0.8f, 1f); + matrices.translate(-x, -iconY, 0); + context.drawItem(icon, x, iconY); + matrices.pop(); + if (PartyFinderScreen.DEBUG) context.drawText(MinecraftClient.getInstance().textRenderer, String.valueOf(optionSlotId), x+8, y, 0xFFFF0000, true); + context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal(message).fillStyle(Style.EMPTY.withUnderline(hovered)), x + 14, y + 3, 0xFFFFFFFF, false); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Option that = (Option) o; + + return message.equals(that.message); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (screen.isWaitingForServer()) return false; + if (button == 0) { + screen.clickAndWaitForServer(this.optionSlotId); + setSelectedOption(this); + } + return true; + } + + @Override + public int hashCode() { + return message.hashCode(); + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntry.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntry.java new file mode 100644 index 00000000..35180ef3 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntry.java @@ -0,0 +1,261 @@ +package de.hysky.skyblocker.skyblock.dungeon.partyfinder; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.mixin.accessor.SkullBlockEntityAccessor; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.PlayerSkinDrawer; +import net.minecraft.client.gui.Selectable; +import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.client.util.DefaultSkinHelper; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.StringNbtReader; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.text.TextColor; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PartyEntry extends ElementListWidget.Entry<PartyEntry> { + + private static final Identifier PARTY_CARD_TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/party_card.png"); + private static final Identifier PARTY_CARD_TEXTURE_HOVER = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/party_card_hover.png"); + private final PartyFinderScreen screen; + private final int slotID; + Player partyLeader; + String floor = "???"; + String dungeon = "???"; + String note = ""; + NbtCompound floorSkullNBT = new NbtCompound(); + Identifier partyLeaderSkin = DefaultSkinHelper.getTexture(); + Player[] partyMembers = new Player[4]; + + int minClassLevel = -1; + int minCatacombsLevel = -1; + + public boolean isLocked() { + return isLocked; + } + + boolean isLocked = false; + Text lockReason = Text.empty(); + + + public PartyEntry(List<Text> tooltips, PartyFinderScreen screen, int slotID) { + this.screen = screen; + this.slotID = slotID; + + Arrays.fill(partyMembers, null); + if (tooltips.isEmpty()) return; + //System.out.println(tooltips); + + MinecraftClient client = MinecraftClient.getInstance(); + Text title = tooltips.get(0); + String partyHost = title.getString().split("'s")[0]; + + int membersIndex = -1; + for (int i = 1; i < tooltips.size(); i++) { + Text text = tooltips.get(i); + String tooltipText = text.getString(); + String lowerCase = tooltipText.toLowerCase(); + //System.out.println("TOOLTIP"+i); + //System.out.println(text.getSiblings()); + if (lowerCase.contains("members:") && membersIndex == -1) { + membersIndex = i + 1; + } else if (lowerCase.contains("class level")) { + Matcher matcher = Pattern.compile("\\d+$").matcher(lowerCase); + if (matcher.find()) minClassLevel = Integer.parseInt(matcher.group()); + } else if (lowerCase.contains("dungeon level")) { + Matcher matcher = Pattern.compile("\\d+$").matcher(lowerCase); + if (matcher.find()) minCatacombsLevel = Integer.parseInt(matcher.group()); + } else if (lowerCase.contains("floor:")) { + floor = tooltipText.split(":")[1].trim(); + if (dungeon.equals("???")) continue; + if (PartyFinderScreen.floorIconsMaster == null || PartyFinderScreen.floorIconsNormal == null) continue; + if (dungeon.contains("master")) { + try { + floorSkullNBT = StringNbtReader.parse(PartyEntryListWidget.BASE_SKULL_NBT.replace("%TEXTURE%", PartyFinderScreen.floorIconsMaster.getOrDefault(floor.toLowerCase(), ""))); + } catch (CommandSyntaxException e) { + throw new RuntimeException(e); + } + } else { + try { + floorSkullNBT = StringNbtReader.parse(PartyEntryListWidget.BASE_SKULL_NBT.replace("%TEXTURE%", PartyFinderScreen.floorIconsNormal.getOrDefault(floor.toLowerCase(), ""))); + } catch (CommandSyntaxException e) { + throw new RuntimeException(e); + } + } + + } else if (lowerCase.contains("dungeon:")) { + dungeon = tooltipText.split(":")[1].trim(); + } else if (!text.getSiblings().isEmpty() && Objects.equals(text.getSiblings().get(0).getStyle().getColor(), TextColor.fromRgb(Formatting.RED.getColorValue())) && !lowerCase.startsWith(" ")) { + isLocked = true; + lockReason = text; + } else if (lowerCase.contains("note:")) { + note = tooltipText.split(":")[1].trim(); + } + } + if (membersIndex != -1) { + for (int i = membersIndex, j = 0; i < membersIndex + 5; i++, j++) { + if (i >= tooltips.size()) continue; + + Text text = tooltips.get(i); + String memberText = text.getString(); + if (!memberText.startsWith(" ")) continue; // Member thingamajigs start with a space + + String[] parts = memberText.split(":", 2); + String playerNameTrim = parts[0].trim(); + + if (playerNameTrim.equals("Empty")) continue; // Don't care about these idiots lol + + List<Text> siblings = text.getSiblings(); + Style nameStyle = !siblings.isEmpty() ? siblings.get(Math.min(1, siblings.size() - 1)).getStyle() : text.getStyle(); + Text playerName = Text.literal(playerNameTrim).setStyle(nameStyle); + String className = parts[1].trim().split(" ")[0]; + int classLevel = -1; + Matcher matcher = Pattern.compile("\\((\\d+)\\)").matcher(parts[1]); + if (matcher.find()) classLevel = Integer.parseInt(matcher.group(1)); + Player player = new Player(playerName, className, classLevel); + + SkullBlockEntityAccessor.invokeFetchProfile(playerNameTrim).thenAccept( + (gameProfile) -> gameProfile.ifPresent(profile -> player.skinTexture = (client.getSkinProvider().getSkinTextures(profile).texture()))); + if (playerNameTrim.equals(partyHost)) { + partyLeader = player; + j--; + } else partyMembers[j] = player; + } + } + + SkullBlockEntityAccessor.invokeFetchProfile(partyHost).thenAccept( + (gameProfile) -> gameProfile.ifPresent(profile -> partyLeaderSkin = client.getSkinProvider().getSkinTextures(profile).texture())); + } + + @Override + public List<? extends Selectable> selectableChildren() { + return List.of(); + } + + @Override + public List<? extends Element> children() { + return List.of(); + } + + @Override + public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + MatrixStack matrices = context.getMatrices(); + matrices.push(); + matrices.translate(x, y, 0); + + if (hovered && !isLocked) context.drawTexture(PARTY_CARD_TEXTURE_HOVER, 0, 0, 0, 0, 336, 64, 336, 64); + else context.drawTexture(PARTY_CARD_TEXTURE, 0, 0, 0, 0, 336, 64, 336, 64); + int mouseXLocal = mouseX - x; + int mouseYLocal = mouseY - y; + + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + context.drawText(textRenderer, this.partyLeader.toText(), 18, 6, 0xFFFFFFFF, true); + + if (PartyFinderScreen.DEBUG) { + context.drawText(textRenderer, String.valueOf(slotID), 166, 6, 0xFFFFFFFF, true); + if (hovered) { + context.drawText(textRenderer, "H", 160, 6, 0xFFFFFFFF, true); + } + } + PlayerSkinDrawer.draw(context, partyLeaderSkin, 6, 6, 8, true, false); + for (int i = 0; i < partyMembers.length; i++) { + Player partyMember = partyMembers[i]; + if (partyMember == null) continue; + context.drawText(textRenderer, partyMember.toText(), 17 + 136 * (i % 2), 24 + 14 * (i / 2), 0xFFFFFFFF, true); + PlayerSkinDrawer.draw(context, partyMember.skinTexture, 6 + 136 * (i % 2), 24 + 14 * (i / 2), 8, true, false); + } + if (minClassLevel > 0) { + context.drawText(textRenderer, "Class " + minClassLevel, 277, 25, 0xFFFFFF00, true); + if (!isLocked && hovered && mouseXLocal >= 276 && mouseXLocal <= 331 && mouseYLocal >= 22 && mouseYLocal <= 35) { + context.drawTooltip(textRenderer, Text.translatable("skyblocker.partyFinder.partyCard.minClassLevel", minClassLevel), mouseXLocal, mouseYLocal); + } + } + if (minCatacombsLevel > 0) { + context.drawText(textRenderer, "Cata " + minCatacombsLevel, 277, 43, 0xFFFFFF00, true); + if (!isLocked && hovered && mouseXLocal >= 276 && mouseXLocal <= 331 && mouseYLocal >= 40 && mouseYLocal <= 53) { + context.drawTooltip(textRenderer, Text.translatable("skyblocker.partyFinder.partyCard.minDungeonLevel", minCatacombsLevel), mouseXLocal, mouseYLocal); + } + } + ItemStack stack = new ItemStack(Items.PLAYER_HEAD); + stack.setNbt(floorSkullNBT); + context.drawItem(stack, 317, 3); + int textWidth = textRenderer.getWidth(floor); + context.drawText(textRenderer, floor, 316 - textWidth, 7, 0x70000000, false); + + context.drawText(textRenderer, note, 5, 51, 0xFFFFFFFF, true); + + if (isLocked) { + matrices.push(); + matrices.translate(0, 0, 100f); + context.fill(0, 0, entryWidth, entryHeight, 0x90000000); + context.drawText(textRenderer, lockReason, entryWidth/2 - textRenderer.getWidth(lockReason)/2, entryHeight/2 - textRenderer.fontHeight/2, 0xFFFFFF, true); + matrices.pop(); + } + + matrices.pop(); + + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + System.out.println("To be clicked" + slotID); + + if (button == 0 && !screen.isWaitingForServer()) { + screen.clickAndWaitForServer(slotID); + return true; + } + return super.mouseClicked(mouseX, mouseY, button); + } + + public static class Player { + public final Text name; + public final String dungeonClass; + public final int classLevel; + public Identifier skinTexture = DefaultSkinHelper.getTexture(); + + Player(Text name, String dungeonClass, int classLevel) { + this.name = name; + this.dungeonClass = dungeonClass; + this.classLevel = classLevel; + } + + public Text toText() { + char dClass = dungeonClass.isEmpty() ? '?' : dungeonClass.charAt(0); + return name.copy().append(Text.literal(" " + dClass + classLevel).setStyle(Style.EMPTY.withColor(Formatting.WHITE))); + } + } + + public static class NoParties extends PartyEntry { + + public NoParties() { + super(List.of(), null, -1); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + return false; + } + + @Override + public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + context.drawCenteredTextWithShadow(textRenderer, Text.translatable("skyblocker.partyFinder.noParties"), x+entryWidth/2, y+entryHeight/2-textRenderer.fontHeight/2, 0xFFFFFFFF); + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntryListWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntryListWidget.java new file mode 100644 index 00000000..de430ae5 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyEntryListWidget.java @@ -0,0 +1,99 @@ +package de.hysky.skyblocker.skyblock.dungeon.partyfinder; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.text.Text; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class PartyEntryListWidget extends ElementListWidget<PartyEntry> { + + protected List<PartyEntry> partyEntries; + + protected boolean isActive = true; + + private String search = ""; + + public static String BASE_SKULL_NBT = """ + { + "SkullOwner": { + "Id": [ + 1215241996, + -1849412511, + -1161255720, + -889217537 + ], + "Properties": { + "textures": [ + { + "Value": "%TEXTURE%" + } + ] + } + } + } + """; + public PartyEntryListWidget(MinecraftClient minecraftClient, int width, int height, int y, int itemHeight) { + super(minecraftClient, width, height, y, itemHeight); + } + + @Ov |
