From ca2bb2ba49fb648d81cf7a594969115ee38c34dd Mon Sep 17 00:00:00 2001 From: esteban4567890 Date: Tue, 6 Feb 2024 00:41:18 +0100 Subject: Visitor helper --- .../hysky/skyblocker/config/SkyblockerConfig.java | 3 + .../config/categories/GeneralCategory.java | 7 + .../hysky/skyblocker/mixin/HandledScreenMixin.java | 21 ++- .../skyblocker/skyblock/garden/VisitorHelper.java | 171 +++++++++++++++++++++ .../resources/assets/skyblocker/lang/en_us.json | 1 + 5 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java index 4acb8064..fd272c71 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java @@ -174,6 +174,9 @@ public class SkyblockerConfig { @SerialEntry public boolean dontStripSkinAlphaValues = true; + @SerialEntry + public boolean visitorHelper = true; + @SerialEntry public TabHudConf tabHud = new TabHudConf(); diff --git a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java index 808b3c2c..bb2fdee5 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -78,6 +78,13 @@ public class GeneralCategory { .controller(ConfigUtils::createBooleanController) .flag(OptionFlag.ASSET_RELOAD) .build()) + .option(Option.createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.general.visitorHelper")) + .binding(defaults.general.visitorHelper, + () -> config.general.visitorHelper, + newValue -> config.general.visitorHelper = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) //Tab Hud .group(OptionGroup.createBuilder() diff --git a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java index 71203381..5d635e27 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java @@ -7,6 +7,7 @@ import de.hysky.skyblocker.skyblock.experiment.ChronomatronSolver; import de.hysky.skyblocker.skyblock.experiment.ExperimentSolver; import de.hysky.skyblocker.skyblock.experiment.SuperpairsSolver; import de.hysky.skyblocker.skyblock.experiment.UltrasequencerSolver; +import de.hysky.skyblocker.skyblock.garden.VisitorHelper; import de.hysky.skyblocker.skyblock.item.ItemProtection; import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; import de.hysky.skyblocker.skyblock.item.WikiLookup; @@ -37,7 +38,6 @@ import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -71,6 +71,20 @@ public abstract class HandledScreenMixin extends Screen } } + @Inject(at = @At("RETURN"), method = "render") + public void skyblocker$renderScreen(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + if (!Utils.isOnSkyblock()) return; + + if (SkyblockerConfigManager.get().general.visitorHelper && Utils.getLocationRaw().equals("garden") && !this.getTitle().getString().contains("Logbook")) + VisitorHelper.renderScreen(this.getTitle().getString(), context, textRenderer, handler, mouseX, mouseY); + } + + @Inject(at = @At("HEAD"), method = "mouseClicked") + public void skyblocker$mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable cir) { + if (SkyblockerConfigManager.get().general.visitorHelper) + VisitorHelper.onMouseClicked(mouseX, mouseY, button, this.textRenderer); + } + @SuppressWarnings("DataFlowIssue") // makes intellij be quiet about this.focusedSlot maybe being null. It's already null checked in mixined method. @Inject(method = "drawMouseoverTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTooltip(Lnet/minecraft/client/font/TextRenderer;Ljava/util/List;Ljava/util/Optional;II)V"), cancellable = true) @@ -167,8 +181,11 @@ public abstract class HandledScreenMixin extends Screen if (ItemProtection.isItemProtected(stack)) ci.cancel(); } - //Prevent selling to NPC shops + if (this.client != null && this.handler instanceof GenericContainerScreenHandler genericContainerScreenHandler && genericContainerScreenHandler.getRows() == 6) { + VisitorHelper.onSlotClick(slot, slotId, this.getTitle().getString()); + + //Prevent selling to NPC shops ItemStack sellItem = this.handler.slots.get(49).getStack(); if (sellItem.getName().getString().equals("Sell Item") || skyblocker$doesLoreContain(sellItem, this.client, "buyback")) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java new file mode 100644 index 00000000..2c7ede30 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java @@ -0,0 +1,171 @@ +package de.hysky.skyblocker.skyblock.garden; + +import java.util.HashMap; +import java.util.Map; + +import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; +import de.hysky.skyblocker.utils.NEURepoManager; +import io.github.moulberry.repo.data.NEUItem; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtList; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text.Serialization; +import net.minecraft.util.Formatting; + +//TODO: check inventory items, sum all repeated items into one +public class VisitorHelper { + private static final Map> itemMap = new HashMap<>(); + private static final Map itemCache = new HashMap<>(); + private static final int TEXT_START_X = 3; + private static final int TEXT_START_Y = 13; + private static final int LINE_SPACING = 3; + + public static void renderScreen(String title, DrawContext context, TextRenderer textRenderer, + ScreenHandler handler, int mouseX, int mouseY) { + if (handler.getCursorStack() == ItemStack.EMPTY) + processVisitorItem(title, handler); + drawScreenItems(context, textRenderer, mouseX, mouseY); + } + + public static void onMouseClicked(double mouseX, double mouseY, int mouseButton, TextRenderer textRenderer) { + int yPosition = TEXT_START_Y; + + for (var entry : itemMap.entrySet()) { + String text = entry.getKey(); + int textWidth = textRenderer.getWidth(text); + int textHeight = textRenderer.fontHeight; + + yPosition += LINE_SPACING + textHeight; + + for (var nestedEntry : entry.getValue().entrySet()) { + String nestedText = nestedEntry.getKey(); + textWidth = textRenderer.getWidth(nestedText); + + if (isMouseOverText((int) mouseX, (int) mouseY, TEXT_START_X, yPosition, textWidth, textHeight)) { + MinecraftClient client = MinecraftClient.getInstance(); + client.player.networkHandler.sendChatMessage("/bz " + nestedText); + return; + } + yPosition += LINE_SPACING + textHeight; + } + } + } + + public static void onSlotClick(Slot slot, int slotId, String title) { + if (slotId == 29 || slotId == 13) { + itemMap.remove(title); + } + } + + private static void processVisitorItem(String title, ScreenHandler handler) { + var visitorItem = handler.getSlot(13).getStack(); + if (visitorItem != null && visitorItem.hasNbt() && visitorItem.getNbt().toString().contains("Times Visited")) { + var acceptButton = handler.getSlot(29).getStack(); + if (acceptButton != null && acceptButton.hasNbt()) { + var acceptButtonNbt = acceptButton.getNbt().getCompound("display"); + if (acceptButtonNbt.getType("Lore") == 9) { + processLore(title, acceptButtonNbt.getList("Lore", 8)); + } + } + } + } + + private static void processLore(String title, NbtList nbtList) { + boolean saveRequiredItems = false; + for (var j = 0; j < nbtList.size(); j++) { + var string = nbtList.getString(j); + if (string.contains("Items Required")) + saveRequiredItems = true; + else if (string.contains("Rewards")) + break; + else if (saveRequiredItems) + updateItemMap(title, string); + } + } + + private static void updateItemMap(String title, String lore) { + var mutableText = Serialization.fromJson(lore); + var split = mutableText.getString().split(" x"); + var itemName = split[0].trim(); + if (!itemName.isEmpty()) { + var amount = split.length == 2 ? Integer.parseInt(split[1].trim()) : 1; + Map nestedMap = itemMap.getOrDefault(title, new HashMap<>()); + if (!nestedMap.containsKey(itemName)) { + nestedMap.put(itemName, amount); + } + if (!itemMap.containsKey(title)) { + itemMap.put(title, nestedMap); + } + } + } + + private static void drawScreenItems(DrawContext context, TextRenderer textRenderer, int mouseX, int mouseY) { + int index = 0; + for (var entry : itemMap.entrySet()) { + var primaryKey = entry.getKey(); + drawTextWithOptionalUnderline(context, textRenderer, primaryKey, TEXT_START_X, + TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), -1, mouseX, mouseY); + index++; + + for (var nestedEntry : entry.getValue().entrySet()) { + index = drawItemEntryWithHover(context, textRenderer, nestedEntry, index, mouseX, mouseY); + } + } + } + + private static int drawItemEntryWithHover(DrawContext context, TextRenderer textRenderer, + Map.Entry nestedEntry, int index, int mouseX, int mouseY) { + var subItem = nestedEntry.getKey(); + var amount = nestedEntry.getValue(); + var item = getCachedItem(subItem); + if (item != null) { + var text = " " + item.getDisplayName() + " x" + amount; + drawTextWithOptionalUnderline(context, textRenderer, text, TEXT_START_X, + TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), -1, mouseX, mouseY); + drawItemStack(context, textRenderer, item, amount, index); + } + return index + 1; + } + + private static NEUItem getCachedItem(String displayName) { + var strippedName = Formatting.strip(displayName); + var cachedItem = itemCache.get(strippedName); + if (cachedItem == null) { + var item = NEURepoManager.NEU_REPO.getItems().getItems().values().stream() + .filter(i -> Formatting.strip(i.getDisplayName()).equals(strippedName)) + .findFirst() + .orElse(null); + if (item != null) { + itemCache.put(strippedName, item); + } + return item; + } + return cachedItem; + } + + private static void drawTextWithOptionalUnderline(DrawContext context, TextRenderer textRenderer, String text, + int x, int y, int color, int mouseX, int mouseY) { + context.drawText(textRenderer, text, x, y, color, true); + if (isMouseOverText(mouseX, mouseY, x, y, textRenderer.getWidth(text), textRenderer.fontHeight)) { + context.drawHorizontalLine(x, x + textRenderer.getWidth(text), y + textRenderer.fontHeight, color); + } + } + + private static boolean isMouseOverText(int mouseX, int mouseY, int x, int y, int width, int height) { + return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; + } + + private static void drawItemStack(DrawContext context, TextRenderer textRenderer, NEUItem item, int amount, + int index) { + var stack = ItemRepository.getItemStack(item.getSkyblockItemId()); + var text = " " + item.getDisplayName() + " x" + amount; + context.drawItem(stack, TEXT_START_X + 2 + textRenderer.getWidth(text), + TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)) - textRenderer.fontHeight + 5); + context.drawText(textRenderer, text, TEXT_START_X, + TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), -1, true); + } +} diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index f17f109e..e28d34bb 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -31,6 +31,7 @@ "text.autoconfig.skyblocker.option.general.experiments.enableSuperpairsSolver": "Enable Superpairs Solver", "text.autoconfig.skyblocker.option.general.experiments.enableUltrasequencerSolver": "Enable Ultrasequencer Solver", "text.autoconfig.skyblocker.option.general.acceptReparty": "Auto accept Reparty", + "text.autoconfig.skyblocker.option.general.visitorHelper": "Visitor helper", "text.autoconfig.skyblocker.option.general.etherwarpOverlay": "Etherwarp Overlay", "text.autoconfig.skyblocker.option.general.fishing": "Fishing Helper", "text.autoconfig.skyblocker.option.general.fishing.enableFishingHelper": "Enable Fishing Helper", -- cgit From 8c65915417c4d994b5febd766aa9a7f508881407 Mon Sep 17 00:00:00 2001 From: esteban4567890 Date: Tue, 6 Feb 2024 00:42:29 +0100 Subject: Garden check to mouse clicked --- src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java index 5d635e27..1cb81778 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java @@ -81,7 +81,7 @@ public abstract class HandledScreenMixin extends Screen @Inject(at = @At("HEAD"), method = "mouseClicked") public void skyblocker$mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable cir) { - if (SkyblockerConfigManager.get().general.visitorHelper) + if (SkyblockerConfigManager.get().general.visitorHelper && Utils.getLocationRaw().equals("garden") ) VisitorHelper.onMouseClicked(mouseX, mouseY, button, this.textRenderer); } -- cgit From b90bdd7851a166b75b32bca3bf4ea56d5537f665 Mon Sep 17 00:00:00 2001 From: esteban4567890 Date: Fri, 9 Feb 2024 13:36:41 +0100 Subject: Fixed NumberFormatException with 4 digit stack --- .../hysky/skyblocker/skyblock/garden/VisitorHelper.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java index 2c7ede30..c4e1468d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java @@ -3,6 +3,11 @@ package de.hysky.skyblocker.skyblock.garden; import java.util.HashMap; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.NumberFormat; + import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.utils.NEURepoManager; import io.github.moulberry.repo.data.NEUItem; @@ -18,6 +23,8 @@ import net.minecraft.util.Formatting; //TODO: check inventory items, sum all repeated items into one public class VisitorHelper { + private static final Logger LOGGER = LoggerFactory.getLogger("Skyblocker Visitor Helper"); + private static final Map> itemMap = new HashMap<>(); private static final Map itemCache = new HashMap<>(); private static final int TEXT_START_X = 3; @@ -92,7 +99,13 @@ public class VisitorHelper { var split = mutableText.getString().split(" x"); var itemName = split[0].trim(); if (!itemName.isEmpty()) { - var amount = split.length == 2 ? Integer.parseInt(split[1].trim()) : 1; + int amount = 1; + try { + amount = split.length == 2 ? NumberFormat.getInstance().parse(split[1].trim()).intValue() : 1; + } catch (Exception e) { + LOGGER.debug("Failed to parse amount for item: " + mutableText.getString()); + return; + } Map nestedMap = itemMap.getOrDefault(title, new HashMap<>()); if (!nestedMap.containsKey(itemName)) { nestedMap.put(itemName, amount); -- cgit From 540821c90e37f9d2aabb74ee6e5ade6a7dec68a5 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sun, 11 Feb 2024 14:14:12 -0500 Subject: Refactor VisitorHelper --- .../hysky/skyblocker/mixin/HandledScreenMixin.java | 4 +- .../skyblocker/skyblock/garden/VisitorHelper.java | 188 +++++++++------------ 2 files changed, 85 insertions(+), 107 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java index 1cb81778..8a1af570 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java @@ -75,13 +75,13 @@ public abstract class HandledScreenMixin extends Screen public void skyblocker$renderScreen(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { if (!Utils.isOnSkyblock()) return; - if (SkyblockerConfigManager.get().general.visitorHelper && Utils.getLocationRaw().equals("garden") && !this.getTitle().getString().contains("Logbook")) + if (SkyblockerConfigManager.get().general.visitorHelper && (Utils.getLocationRaw().equals("garden") && !getTitle().getString().contains("Logbook") || getTitle().getString().startsWith("Bazaar"))) VisitorHelper.renderScreen(this.getTitle().getString(), context, textRenderer, handler, mouseX, mouseY); } @Inject(at = @At("HEAD"), method = "mouseClicked") public void skyblocker$mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable cir) { - if (SkyblockerConfigManager.get().general.visitorHelper && Utils.getLocationRaw().equals("garden") ) + if (SkyblockerConfigManager.get().general.visitorHelper && (Utils.getLocationRaw().equals("garden") && !getTitle().getString().contains("Logbook") || getTitle().getString().startsWith("Bazaar"))) VisitorHelper.onMouseClicked(mouseX, mouseY, button, this.textRenderer); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java index c4e1468d..3c049f69 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java @@ -1,38 +1,40 @@ package de.hysky.skyblocker.skyblock.garden; -import java.util.HashMap; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.NumberFormat; - import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.utils.NEURepoManager; +import de.hysky.skyblocker.utils.scheduler.MessageScheduler; import io.github.moulberry.repo.data.NEUItem; -import net.minecraft.client.MinecraftClient; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtList; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; import net.minecraft.text.Text.Serialization; import net.minecraft.util.Formatting; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.NumberFormat; +import java.util.HashMap; +import java.util.Map; //TODO: check inventory items, sum all repeated items into one public class VisitorHelper { private static final Logger LOGGER = LoggerFactory.getLogger("Skyblocker Visitor Helper"); - private static final Map> itemMap = new HashMap<>(); - private static final Map itemCache = new HashMap<>(); - private static final int TEXT_START_X = 3; - private static final int TEXT_START_Y = 13; + private static final Map> itemMap = new HashMap<>(); + private static final Map itemCache = new HashMap<>(); + private static final int TEXT_START_X = 4; + private static final int TEXT_START_Y = 4; private static final int LINE_SPACING = 3; - public static void renderScreen(String title, DrawContext context, TextRenderer textRenderer, - ScreenHandler handler, int mouseX, int mouseY) { + public static void renderScreen(String title, DrawContext context, TextRenderer textRenderer, ScreenHandler handler, int mouseX, int mouseY) { if (handler.getCursorStack() == ItemStack.EMPTY) processVisitorItem(title, handler); drawScreenItems(context, textRenderer, mouseX, mouseY); @@ -41,20 +43,18 @@ public class VisitorHelper { public static void onMouseClicked(double mouseX, double mouseY, int mouseButton, TextRenderer textRenderer) { int yPosition = TEXT_START_Y; - for (var entry : itemMap.entrySet()) { - String text = entry.getKey(); - int textWidth = textRenderer.getWidth(text); + for (Map.Entry> visitorEntry : itemMap.entrySet()) { + int textWidth; int textHeight = textRenderer.fontHeight; yPosition += LINE_SPACING + textHeight; - for (var nestedEntry : entry.getValue().entrySet()) { - String nestedText = nestedEntry.getKey(); - textWidth = textRenderer.getWidth(nestedText); + for (Object2IntMap.Entry itemEntry : visitorEntry.getValue().object2IntEntrySet()) { + String itemText = itemEntry.getKey(); + textWidth = textRenderer.getWidth(itemText); - if (isMouseOverText((int) mouseX, (int) mouseY, TEXT_START_X, yPosition, textWidth, textHeight)) { - MinecraftClient client = MinecraftClient.getInstance(); - client.player.networkHandler.sendChatMessage("/bz " + nestedText); + if (isMouseOverText(mouseX, mouseY, TEXT_START_X, yPosition, textWidth, textHeight)) { + MessageScheduler.INSTANCE.sendMessageAfterCooldown("/bz " + itemText); return; } yPosition += LINE_SPACING + textHeight; @@ -68,117 +68,95 @@ public class VisitorHelper { } } - private static void processVisitorItem(String title, ScreenHandler handler) { - var visitorItem = handler.getSlot(13).getStack(); - if (visitorItem != null && visitorItem.hasNbt() && visitorItem.getNbt().toString().contains("Times Visited")) { - var acceptButton = handler.getSlot(29).getStack(); - if (acceptButton != null && acceptButton.hasNbt()) { - var acceptButtonNbt = acceptButton.getNbt().getCompound("display"); - if (acceptButtonNbt.getType("Lore") == 9) { - processLore(title, acceptButtonNbt.getList("Lore", 8)); - } - } - } + private static void processVisitorItem(String visitorName, ScreenHandler handler) { + ItemStack visitorItem = handler.getSlot(13).getStack(); + if (visitorItem == null || !visitorItem.hasNbt() || !visitorItem.getNbt().asString().contains("Times Visited")) return; + ItemStack acceptButton = handler.getSlot(29).getStack(); + if (acceptButton == null) return; + NbtCompound acceptButtonNbt = acceptButton.getSubNbt("display"); + if (acceptButtonNbt == null || !acceptButtonNbt.contains("Lore", NbtElement.LIST_TYPE)) return; + processLore(visitorName, acceptButtonNbt.getList("Lore", NbtElement.STRING_TYPE)); } - private static void processLore(String title, NbtList nbtList) { + private static void processLore(String visitorName, NbtList loreList) { boolean saveRequiredItems = false; - for (var j = 0; j < nbtList.size(); j++) { - var string = nbtList.getString(j); - if (string.contains("Items Required")) + for (int i = 0; i < loreList.size(); i++) { + String lore = loreList.getString(i); + if (lore.contains("Items Required")) saveRequiredItems = true; - else if (string.contains("Rewards")) + else if (lore.contains("Rewards")) break; else if (saveRequiredItems) - updateItemMap(title, string); + updateItemMap(visitorName, lore); } } - private static void updateItemMap(String title, String lore) { - var mutableText = Serialization.fromJson(lore); - var split = mutableText.getString().split(" x"); - var itemName = split[0].trim(); - if (!itemName.isEmpty()) { - int amount = 1; - try { - amount = split.length == 2 ? NumberFormat.getInstance().parse(split[1].trim()).intValue() : 1; - } catch (Exception e) { - LOGGER.debug("Failed to parse amount for item: " + mutableText.getString()); - return; - } - Map nestedMap = itemMap.getOrDefault(title, new HashMap<>()); - if (!nestedMap.containsKey(itemName)) { - nestedMap.put(itemName, amount); - } - if (!itemMap.containsKey(title)) { - itemMap.put(title, nestedMap); - } + private static void updateItemMap(String visitorName, String lore) { + Text itemText = Serialization.fromJson(lore); + String[] splitItemText = itemText.getString().split(" x"); + String itemName = splitItemText[0].trim(); + if (itemName.isEmpty()) return; + try { + int amount = splitItemText.length == 2 ? NumberFormat.getInstance().parse(splitItemText[1].trim()).intValue() : 1; + Object2IntMap visitorMap = itemMap.getOrDefault(visitorName, new Object2IntOpenHashMap<>()); + visitorMap.putIfAbsent(itemName, amount); + itemMap.putIfAbsent(visitorName, visitorMap); + } catch (Exception e) { + LOGGER.error("[Skyblocker Visitor Helper] Failed to parse item: " + itemText.getString(), e); } } private static void drawScreenItems(DrawContext context, TextRenderer textRenderer, int mouseX, int mouseY) { int index = 0; - for (var entry : itemMap.entrySet()) { - var primaryKey = entry.getKey(); - drawTextWithOptionalUnderline(context, textRenderer, primaryKey, TEXT_START_X, - TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), -1, mouseX, mouseY); + for (Map.Entry> visitorEntry : itemMap.entrySet()) { + String visitorName = visitorEntry.getKey(); + drawTextWithOptionalUnderline(context, textRenderer, Text.literal(visitorName), TEXT_START_X, TEXT_START_Y + index * (LINE_SPACING + textRenderer.fontHeight), mouseX, mouseY); index++; - for (var nestedEntry : entry.getValue().entrySet()) { - index = drawItemEntryWithHover(context, textRenderer, nestedEntry, index, mouseX, mouseY); + for (Object2IntMap.Entry itemEntry : visitorEntry.getValue().object2IntEntrySet()) { + index = drawItemEntryWithHover(context, textRenderer, itemEntry, index, mouseX, mouseY); } } } - private static int drawItemEntryWithHover(DrawContext context, TextRenderer textRenderer, - Map.Entry nestedEntry, int index, int mouseX, int mouseY) { - var subItem = nestedEntry.getKey(); - var amount = nestedEntry.getValue(); - var item = getCachedItem(subItem); - if (item != null) { - var text = " " + item.getDisplayName() + " x" + amount; - drawTextWithOptionalUnderline(context, textRenderer, text, TEXT_START_X, - TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), -1, mouseX, mouseY); - drawItemStack(context, textRenderer, item, amount, index); + private static int drawItemEntryWithHover(DrawContext context, TextRenderer textRenderer, Map.Entry itemEntry, int index, int mouseX, int mouseY) { + String itemName = itemEntry.getKey(); + int amount = itemEntry.getValue(); + ItemStack stack = getCachedItem(itemName); + if (stack != null) { + drawItemEntryWithHover(context, textRenderer, stack, amount, index, mouseX, mouseY); } return index + 1; } - private static NEUItem getCachedItem(String displayName) { - var strippedName = Formatting.strip(displayName); - var cachedItem = itemCache.get(strippedName); - if (cachedItem == null) { - var item = NEURepoManager.NEU_REPO.getItems().getItems().values().stream() - .filter(i -> Formatting.strip(i.getDisplayName()).equals(strippedName)) - .findFirst() - .orElse(null); - if (item != null) { - itemCache.put(strippedName, item); - } - return item; - } - return cachedItem; + private static ItemStack getCachedItem(String displayName) { + String strippedName = Formatting.strip(displayName); + ItemStack cachedStack = itemCache.get(strippedName); + if (cachedStack != null) return cachedStack; + NEUItem neuItem = NEURepoManager.NEU_REPO.getItems().getItems().values().stream() + .filter(i -> Formatting.strip(i.getDisplayName()).equals(strippedName)) + .findFirst() + .orElse(null); + if (neuItem == null) return null; + ItemStack stack = ItemRepository.getItemStack(neuItem.getSkyblockItemId()); + itemCache.put(strippedName, stack); + return stack; + } + + private static void drawItemEntryWithHover(DrawContext context, TextRenderer textRenderer, ItemStack stack, int amount, int index, int mouseX, int mousseY) { + Text text = Serialization.fromJson(stack.getSubNbt("display").getString("Name")).append(" x" + amount); + drawTextWithOptionalUnderline(context, textRenderer, text, TEXT_START_X + 8, TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), mouseX, mousseY); + context.drawItem(stack, TEXT_START_X + 10 + textRenderer.getWidth(text), TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)) - textRenderer.fontHeight + 5); } - private static void drawTextWithOptionalUnderline(DrawContext context, TextRenderer textRenderer, String text, - int x, int y, int color, int mouseX, int mouseY) { - context.drawText(textRenderer, text, x, y, color, true); + private static void drawTextWithOptionalUnderline(DrawContext context, TextRenderer textRenderer, Text text, int x, int y, int mouseX, int mouseY) { + context.drawText(textRenderer, text, x, y, -1, true); if (isMouseOverText(mouseX, mouseY, x, y, textRenderer.getWidth(text), textRenderer.fontHeight)) { - context.drawHorizontalLine(x, x + textRenderer.getWidth(text), y + textRenderer.fontHeight, color); + context.drawHorizontalLine(x, x + textRenderer.getWidth(text), y + textRenderer.fontHeight, -1); } } - private static boolean isMouseOverText(int mouseX, int mouseY, int x, int y, int width, int height) { + private static boolean isMouseOverText(double mouseX, double mouseY, int x, int y, int width, int height) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } - - private static void drawItemStack(DrawContext context, TextRenderer textRenderer, NEUItem item, int amount, - int index) { - var stack = ItemRepository.getItemStack(item.getSkyblockItemId()); - var text = " " + item.getDisplayName() + " x" + amount; - context.drawItem(stack, TEXT_START_X + 2 + textRenderer.getWidth(text), - TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)) - textRenderer.fontHeight + 5); - context.drawText(textRenderer, text, TEXT_START_X, - TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), -1, true); - } } -- cgit