From a7ba4feaaacc95b505b75ec78a169fed66aead93 Mon Sep 17 00:00:00 2001 From: victo Date: Wed, 13 Sep 2023 20:16:32 +0200 Subject: [PATCH 1/5] Add tooltip display for personal compactor items This update integrates a tooltip display for personal compactor items in the Skyblocker mod. The tooltip shows the contents of the personal compactor when hovered over. This is useful for players to quickly check the contents of their compactor without needing to open it. The commit includes creating a new Java file 'CompactorPreviewTooltipComponent.java' for the compactor tooltip component, adding new inject method 'skyblocker$addTooltipComponent' in 'HandledScreenMixin.java' executed when drawing mouseover tooltip, adding 'DrawContextInvoker.java' for invoking the 'drawTooltip' method in the 'DrawContext' class, and adding 'getItemStack' method in the 'ItemRegistry.java'. --- .../skyblocker/mixin/HandledScreenMixin.java | 115 ++++++++++++++++-- .../mixin/accessor/DrawContextInvoker.java | 18 +++ .../CompactorPreviewTooltipComponent.java | 60 +++++++++ .../skyblock/itemlist/ItemRegistry.java | 4 + src/main/resources/skyblocker.mixins.json | 3 +- 5 files changed, 192 insertions(+), 8 deletions(-) create mode 100644 src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/DrawContextInvoker.java create mode 100644 src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorPreviewTooltipComponent.java diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java index eccd63e653..4959f8562b 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java @@ -2,28 +2,33 @@ import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.mixin.accessor.DrawContextInvoker; import me.xmrvizzy.skyblocker.skyblock.BackpackPreview; -import me.xmrvizzy.skyblocker.skyblock.dungeon.DungeonChestProfit; import me.xmrvizzy.skyblocker.skyblock.experiment.ChronomatronSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.ExperimentSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.SuperpairsSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.UltrasequencerSolver; +import me.xmrvizzy.skyblocker.skyblock.item.CompactorPreviewTooltipComponent; import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup; +import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry; import me.xmrvizzy.skyblocker.utils.Utils; import me.xmrvizzy.skyblocker.utils.render.gui.ContainerSolver; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.gui.tooltip.HoveredTooltipPositioner; +import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.inventory.SimpleInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.screen.GenericContainerScreenHandler; -import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.nbt.NbtCompound; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.text.MutableText; +import net.minecraft.text.Style; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import org.jetbrains.annotations.Nullable; -import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -34,10 +39,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; - +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; @Mixin(HandledScreen.class) public abstract class HandledScreenMixin extends Screen { @@ -45,6 +50,17 @@ public abstract class HandledScreenMixin extends Screen { @Nullable protected Slot focusedSlot; + @Unique + private static final Map personalCompactorTypeToSlot = new HashMap<>(); + // Lines, and slots per lines + static { + personalCompactorTypeToSlot.put("4000", new int[]{1,1}); + personalCompactorTypeToSlot.put("5000", new int[]{1,3}); + personalCompactorTypeToSlot.put("6000", new int[]{1,7}); + personalCompactorTypeToSlot.put("7000", new int[]{2,6}); + personalCompactorTypeToSlot.put("default", new int[]{1,6}); + } + protected HandledScreenMixin(Text title) { super(title); } @@ -80,6 +96,81 @@ protected HandledScreenMixin(Text title) { return skyblocker$experimentSolvers$getStack(slot, stack); } + @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) + private void skyblocker$addTooltipComponent(DrawContext context, int x, int y, CallbackInfo ci) { + if (this.focusedSlot == null || this.client == null) return; + ItemStack stack = this.focusedSlot.getStack(); + String internalName = ItemRegistry.getInternalName(stack); + // PERSONAL COMPACTOR + if (internalName.contains("PERSONAL_COMPACTOR_") || internalName.contains("PERSONAL_DELETOR_")) { + String prefix; + String itemSlotPrefix; + if (internalName.contains("PERSONAL_COMPACTOR_")) { + prefix = "PERSONAL_COMPACTOR_"; + itemSlotPrefix = "personal_compact_"; + } else { + prefix = "PERSONAL_DELETOR_"; + itemSlotPrefix = "personal_deletor_"; + } + + // Find the line to insert component + int targetIndex = -1; + int lineCount = 0; + List tooltips = Screen.getTooltipFromItem(this.client, stack); + for (int i = 0; i < tooltips.size(); i++) { + if (tooltips.get(i).getString().isEmpty()) { + lineCount += 1; + } + if (lineCount == 2) { + targetIndex = i; + break; + } + } + if (targetIndex == -1) return; + List components = new java.util.ArrayList<>(tooltips.stream().map(Text::asOrderedText).map(TooltipComponent::of).toList()); + + // STUFF + String internalID = ItemRegistry.getInternalName(stack); + String compactorType = internalID.replaceFirst(prefix, ""); + int[] dimensions = personalCompactorTypeToSlot.containsKey(compactorType) ? personalCompactorTypeToSlot.get(compactorType) : personalCompactorTypeToSlot.get("default"); + + NbtCompound nbt = stack.getNbt(); + if (nbt == null || !nbt.contains("ExtraAttributes", 10)) { + return; + } + NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); + Set attributesKeys = extraAttributes.getKeys(); + List compactorItems = attributesKeys.stream().filter(s -> s.contains(itemSlotPrefix)).toList(); + Map slotAndItem = new HashMap<>(); + + compactorItems.forEach(s -> slotAndItem.put(getNumberAtEnd(s, itemSlotPrefix), ItemRegistry.getItemStack(extraAttributes.getString(s)))); + + + components.add(targetIndex, new CompactorPreviewTooltipComponent(slotAndItem, dimensions)); + components.add(targetIndex, TooltipComponent.of(Text.literal(" ").append( + Text.literal("Contents:").fillStyle(Style.EMPTY + .withItalic(true))) + .asOrderedText())); + if (attributesKeys.stream().anyMatch(s -> s.contains("PERSONAL_DELETOR_ACTIVE"))) { + MutableText isActiveText = Text.literal("Active: "); + if (extraAttributes.getBoolean("PERSONAL_DELETOR_ACTIVE")) { + components.add(targetIndex, TooltipComponent.of(isActiveText.append( + Text.literal("YES").fillStyle(Style.EMPTY.withBold(true).withColor(Formatting.GREEN)) + ).asOrderedText() + )); + } else { + components.add(targetIndex, TooltipComponent.of(isActiveText.append( + Text.literal("NO").fillStyle(Style.EMPTY.withBold(true).withColor(Formatting.RED)) + ).asOrderedText() + )); + } + } + ((DrawContextInvoker) context).invokeDrawTooltip(textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); + ci.cancel(); + + } + } + @Unique private ItemStack skyblocker$experimentSolvers$getStack(Slot slot, ItemStack stack) { ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver(); @@ -110,4 +201,14 @@ protected HandledScreenMixin(Text title) { } } } + + @Unique + private static Integer getNumberAtEnd(String str, String attributesKey) { + try { + String numberPartOfTheString = str.replace(attributesKey, ""); + return Integer.parseInt(numberPartOfTheString); + } catch (NumberFormatException e) { + return 0; + } + } } diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/DrawContextInvoker.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/DrawContextInvoker.java new file mode 100644 index 0000000000..55ef077475 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/DrawContextInvoker.java @@ -0,0 +1,18 @@ +package me.xmrvizzy.skyblocker.mixin.accessor; + +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.gui.tooltip.TooltipPositioner; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.List; + +@Mixin(DrawContext.class) +public interface DrawContextInvoker { + + @SuppressWarnings("unused") + @Invoker("drawTooltip") + void invokeDrawTooltip(TextRenderer textRenderer, List components, int x, int y, TooltipPositioner positioner); +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorPreviewTooltipComponent.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorPreviewTooltipComponent.java new file mode 100644 index 0000000000..e916a94b5f --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorPreviewTooltipComponent.java @@ -0,0 +1,60 @@ +package me.xmrvizzy.skyblocker.skyblock.item; + +import me.xmrvizzy.skyblocker.SkyblockerMod; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; + +import java.util.Map; + +public class CompactorPreviewTooltipComponent implements TooltipComponent { + + private static final Identifier INVENTORY_TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/inventory_background.png"); + + Map items; + int[] dimensions; + + public CompactorPreviewTooltipComponent(Map items, int[] dimensions) { + this.items = items; + this.dimensions = dimensions; + } + @Override + public int getHeight() { + return dimensions[0] * 18 + 14; + } + + @Override + public int getWidth(TextRenderer textRenderer) { + return dimensions[1] * 18 + 14; + } + + @Override + public void drawItems(TextRenderer textRenderer, int x, int y, DrawContext context) { + context.drawTexture(INVENTORY_TEXTURE, x, y, 0, 0, 7 + dimensions[1] * 18, 7); + context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions[1] * 18, y, 169, 0, 7, 7); + + for (int i = 0; i < dimensions[0]; i++) { + context.drawTexture(INVENTORY_TEXTURE, x, y + 7 + i * 18, 0, 7, 7, 18); + for (int j = 0; j < dimensions[1]; j++) { + context.drawTexture(INVENTORY_TEXTURE, x + 7 + j * 18, y + 7 + i * 18, 7, 7, 18, 18); + } + context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions[1] * 18, y + 7 + i * 18, 169, 7, 7, 18); + } + context.drawTexture(INVENTORY_TEXTURE, x, y + 7 + dimensions[0] * 18, 0, 25, 7 + dimensions[1] * 18, 7); + context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions[1] * 18, y + 7 + dimensions[0] * 18, 169, 25, 7, 7); + + MatrixStack matrices = context.getMatrices(); + for (Integer i : items.keySet()) { + int itemX = x + i % dimensions[1] * 18 + 8; + int itemY = y + i / dimensions[1] * 18 + 8; + matrices.push(); + matrices.translate(0, 0, 200); + context.drawItem(items.get(i), itemX, itemY); + context.drawItemInSlot(textRenderer, items.get(i), itemX, itemY); + matrices.pop(); + } + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java index a4b566e8be..426e807bc4 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/itemlist/ItemRegistry.java @@ -124,5 +124,9 @@ public static String getInternalName(ItemStack itemStack) { if (itemStack.getNbt() == null) return ""; return itemStack.getNbt().getCompound("ExtraAttributes").getString("id"); } + + public static ItemStack getItemStack(String internalName) { + return itemsMap.get(internalName); + } } diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json index 9d2ce7c2f8..d257d989d0 100644 --- a/src/main/resources/skyblocker.mixins.json +++ b/src/main/resources/skyblocker.mixins.json @@ -29,7 +29,8 @@ "accessor.PlayerListHudAccessor", "accessor.RecipeBookWidgetAccessor", "accessor.ScreenAccessor", - "accessor.WorldRendererAccessor" + "accessor.WorldRendererAccessor", + "accessor.DrawContextInvoker" ], "injectors": { "defaultRequire": 1 From 992178bef293e0b31a2230ff4193d2ed99997bf0 Mon Sep 17 00:00:00 2001 From: victo Date: Wed, 13 Sep 2023 22:04:17 +0200 Subject: [PATCH 2/5] Improved personal compactor UI with tooltip display Made it so it doesn't render the slots if no items (mainly for AH) --- .../xmrvizzy/skyblocker/mixin/HandledScreenMixin.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java index 4959f8562b..e16568a602 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java @@ -143,6 +143,17 @@ protected HandledScreenMixin(Text title) { List compactorItems = attributesKeys.stream().filter(s -> s.contains(itemSlotPrefix)).toList(); Map slotAndItem = new HashMap<>(); + if (compactorItems.isEmpty()) { + int slotsCount = (dimensions[0] * dimensions[1]); + components.add(targetIndex, TooltipComponent.of(Text.literal( + slotsCount + (slotsCount == 1 ? " slot": " slots")) + .fillStyle(Style.EMPTY.withColor(Formatting.DARK_GRAY)).asOrderedText())); + + ((DrawContextInvoker) context).invokeDrawTooltip(textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); + ci.cancel(); + return; + } + compactorItems.forEach(s -> slotAndItem.put(getNumberAtEnd(s, itemSlotPrefix), ItemRegistry.getItemStack(extraAttributes.getString(s)))); From df96aa7bb5bb79a78988ba6701e65a5de3a9ecf2 Mon Sep 17 00:00:00 2001 From: vicisacat Date: Thu, 14 Sep 2023 15:54:08 +0200 Subject: [PATCH 3/5] "Refactor CompactorDeletorPreview logic for better structure" Split the logic for CompactorDeletorPreview to reduce the complexity within the HandledScreenMixin.java file. This change helps to make the code simpler and easier to maintain. --- .../skyblocker/mixin/HandledScreenMixin.java | 130 ++---------------- .../item/CompactorDeletorPreview.java | 122 ++++++++++++++++ 2 files changed, 135 insertions(+), 117 deletions(-) create mode 100644 src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorDeletorPreview.java diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java index e16568a602..ddcbb33fd2 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java @@ -8,7 +8,7 @@ import me.xmrvizzy.skyblocker.skyblock.experiment.ExperimentSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.SuperpairsSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.UltrasequencerSolver; -import me.xmrvizzy.skyblocker.skyblock.item.CompactorPreviewTooltipComponent; +import me.xmrvizzy.skyblocker.skyblock.item.CompactorDeletorPreview; import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup; import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry; import me.xmrvizzy.skyblocker.utils.Utils; @@ -16,18 +16,12 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.gui.tooltip.HoveredTooltipPositioner; -import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.inventory.SimpleInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; -import net.minecraft.text.MutableText; -import net.minecraft.text.Style; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -39,10 +33,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.Set; @Mixin(HandledScreen.class) public abstract class HandledScreenMixin extends Screen { @@ -50,17 +41,6 @@ public abstract class HandledScreenMixin extends Screen { @Nullable protected Slot focusedSlot; - @Unique - private static final Map personalCompactorTypeToSlot = new HashMap<>(); - // Lines, and slots per lines - static { - personalCompactorTypeToSlot.put("4000", new int[]{1,1}); - personalCompactorTypeToSlot.put("5000", new int[]{1,3}); - personalCompactorTypeToSlot.put("6000", new int[]{1,7}); - personalCompactorTypeToSlot.put("7000", new int[]{2,6}); - personalCompactorTypeToSlot.put("default", new int[]{1,6}); - } - protected HandledScreenMixin(Text title) { super(title); } @@ -72,8 +52,12 @@ protected HandledScreenMixin(Text title) { } } - @Inject(at = @At("HEAD"), method = "drawMouseoverTooltip", cancellable = true) + @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) public void skyblocker$drawMouseOverTooltip(DrawContext context, int x, int y, CallbackInfo ci) { + ItemStack stack = this.focusedSlot.getStack(); + String internalName = ItemRegistry.getInternalName(stack); + // Hide Empty Tooltips if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.hideEmptyTooltips && this.focusedSlot != null && focusedSlot.getStack().getName().getString().equals(" ")) { ci.cancel(); @@ -81,7 +65,13 @@ protected HandledScreenMixin(Text title) { // Backpack Preview boolean shiftDown = SkyblockerConfig.get().general.backpackPreviewWithoutShift ^ Screen.hasShiftDown(); - if (this.client != null && this.client.player != null && this.focusedSlot != null && shiftDown && this.getTitle().getString().equals("Storage") && this.focusedSlot.inventory != this.client.player.getInventory() && BackpackPreview.renderPreview(context, this.focusedSlot.getIndex(), x, y)) { + if (this.client == null || this.client.player == null) return; + if (shiftDown && this.getTitle().getString().equals("Storage") && this.focusedSlot.inventory != this.client.player.getInventory() && BackpackPreview.renderPreview(context, this.focusedSlot.getIndex(), x, y)) { + ci.cancel(); + } + + // Compactor Preview + if ((internalName.contains("PERSONAL_COMPACTOR_") || internalName.contains("PERSONAL_DELETOR_")) && CompactorDeletorPreview.displayCompactorDeletorPreview((DrawContextInvoker) context, x, y, stack)) { ci.cancel(); } } @@ -96,91 +86,7 @@ protected HandledScreenMixin(Text title) { return skyblocker$experimentSolvers$getStack(slot, stack); } - @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) - private void skyblocker$addTooltipComponent(DrawContext context, int x, int y, CallbackInfo ci) { - if (this.focusedSlot == null || this.client == null) return; - ItemStack stack = this.focusedSlot.getStack(); - String internalName = ItemRegistry.getInternalName(stack); - // PERSONAL COMPACTOR - if (internalName.contains("PERSONAL_COMPACTOR_") || internalName.contains("PERSONAL_DELETOR_")) { - String prefix; - String itemSlotPrefix; - if (internalName.contains("PERSONAL_COMPACTOR_")) { - prefix = "PERSONAL_COMPACTOR_"; - itemSlotPrefix = "personal_compact_"; - } else { - prefix = "PERSONAL_DELETOR_"; - itemSlotPrefix = "personal_deletor_"; - } - - // Find the line to insert component - int targetIndex = -1; - int lineCount = 0; - List tooltips = Screen.getTooltipFromItem(this.client, stack); - for (int i = 0; i < tooltips.size(); i++) { - if (tooltips.get(i).getString().isEmpty()) { - lineCount += 1; - } - if (lineCount == 2) { - targetIndex = i; - break; - } - } - if (targetIndex == -1) return; - List components = new java.util.ArrayList<>(tooltips.stream().map(Text::asOrderedText).map(TooltipComponent::of).toList()); - - // STUFF - String internalID = ItemRegistry.getInternalName(stack); - String compactorType = internalID.replaceFirst(prefix, ""); - int[] dimensions = personalCompactorTypeToSlot.containsKey(compactorType) ? personalCompactorTypeToSlot.get(compactorType) : personalCompactorTypeToSlot.get("default"); - - NbtCompound nbt = stack.getNbt(); - if (nbt == null || !nbt.contains("ExtraAttributes", 10)) { - return; - } - NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); - Set attributesKeys = extraAttributes.getKeys(); - List compactorItems = attributesKeys.stream().filter(s -> s.contains(itemSlotPrefix)).toList(); - Map slotAndItem = new HashMap<>(); - - if (compactorItems.isEmpty()) { - int slotsCount = (dimensions[0] * dimensions[1]); - components.add(targetIndex, TooltipComponent.of(Text.literal( - slotsCount + (slotsCount == 1 ? " slot": " slots")) - .fillStyle(Style.EMPTY.withColor(Formatting.DARK_GRAY)).asOrderedText())); - - ((DrawContextInvoker) context).invokeDrawTooltip(textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); - ci.cancel(); - return; - } - - compactorItems.forEach(s -> slotAndItem.put(getNumberAtEnd(s, itemSlotPrefix), ItemRegistry.getItemStack(extraAttributes.getString(s)))); - - - components.add(targetIndex, new CompactorPreviewTooltipComponent(slotAndItem, dimensions)); - components.add(targetIndex, TooltipComponent.of(Text.literal(" ").append( - Text.literal("Contents:").fillStyle(Style.EMPTY - .withItalic(true))) - .asOrderedText())); - if (attributesKeys.stream().anyMatch(s -> s.contains("PERSONAL_DELETOR_ACTIVE"))) { - MutableText isActiveText = Text.literal("Active: "); - if (extraAttributes.getBoolean("PERSONAL_DELETOR_ACTIVE")) { - components.add(targetIndex, TooltipComponent.of(isActiveText.append( - Text.literal("YES").fillStyle(Style.EMPTY.withBold(true).withColor(Formatting.GREEN)) - ).asOrderedText() - )); - } else { - components.add(targetIndex, TooltipComponent.of(isActiveText.append( - Text.literal("NO").fillStyle(Style.EMPTY.withBold(true).withColor(Formatting.RED)) - ).asOrderedText() - )); - } - } - ((DrawContextInvoker) context).invokeDrawTooltip(textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); - ci.cancel(); - } - } @Unique private ItemStack skyblocker$experimentSolvers$getStack(Slot slot, ItemStack stack) { @@ -212,14 +118,4 @@ protected HandledScreenMixin(Text title) { } } } - - @Unique - private static Integer getNumberAtEnd(String str, String attributesKey) { - try { - String numberPartOfTheString = str.replace(attributesKey, ""); - return Integer.parseInt(numberPartOfTheString); - } catch (NumberFormatException e) { - return 0; - } - } } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorDeletorPreview.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorDeletorPreview.java new file mode 100644 index 0000000000..70a37b8aeb --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorDeletorPreview.java @@ -0,0 +1,122 @@ +package me.xmrvizzy.skyblocker.skyblock.item; + +import me.xmrvizzy.skyblocker.mixin.accessor.DrawContextInvoker; +import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tooltip.HoveredTooltipPositioner; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.text.MutableText; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class CompactorDeletorPreview { + + private static final MinecraftClient mcClient = MinecraftClient.getInstance(); + private static final Map personalCompactorTypeToSlot = new HashMap<>(); + // Lines, and slots per lines + static { + personalCompactorTypeToSlot.put("4000", new int[]{1,1}); + personalCompactorTypeToSlot.put("5000", new int[]{1,3}); + personalCompactorTypeToSlot.put("6000", new int[]{1,7}); + personalCompactorTypeToSlot.put("7000", new int[]{2,6}); + personalCompactorTypeToSlot.put("default", new int[]{1,6}); + } + + public static boolean displayCompactorDeletorPreview(DrawContextInvoker context, int x, int y, ItemStack stack) { + String internalName = ItemRegistry.getInternalName(stack); + + String prefix; + String itemSlotPrefix; + if (internalName.contains("PERSONAL_COMPACTOR_")) { + prefix = "PERSONAL_COMPACTOR_"; + itemSlotPrefix = "personal_compact_"; + } else { + prefix = "PERSONAL_DELETOR_"; + itemSlotPrefix = "personal_deletor_"; + } + + // Find the line to insert component + int targetIndex = -1; + int lineCount = 0; + + List tooltips = Screen.getTooltipFromItem(mcClient, stack); + for (int i = 0; i < tooltips.size(); i++) { + if (tooltips.get(i).getString().isEmpty()) { + lineCount += 1; + } + if (lineCount == 2) { + targetIndex = i; + break; + } + } + if (targetIndex == -1) return false; + List components = new java.util.ArrayList<>(tooltips.stream().map(Text::asOrderedText).map(TooltipComponent::of).toList()); + + // STUFF + String internalID = ItemRegistry.getInternalName(stack); + String compactorType = internalID.replaceFirst(prefix, ""); + int[] dimensions = personalCompactorTypeToSlot.containsKey(compactorType) ? personalCompactorTypeToSlot.get(compactorType) : personalCompactorTypeToSlot.get("default"); + + NbtCompound nbt = stack.getNbt(); + if (nbt == null || !nbt.contains("ExtraAttributes", 10)) { + return false; + } + NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); + Set attributesKeys = extraAttributes.getKeys(); + List compactorItems = attributesKeys.stream().filter(s -> s.contains(itemSlotPrefix)).toList(); + Map slotAndItem = new HashMap<>(); + + if (compactorItems.isEmpty()) { + int slotsCount = (dimensions[0] * dimensions[1]); + components.add(targetIndex, TooltipComponent.of(Text.literal( + slotsCount + (slotsCount == 1 ? " slot": " slots")) + .fillStyle(Style.EMPTY.withColor(Formatting.DARK_GRAY)).asOrderedText())); + + context.invokeDrawTooltip(mcClient.textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); + return true; + } + + compactorItems.forEach(s -> slotAndItem.put(getNumberAtEnd(s, itemSlotPrefix), ItemRegistry.getItemStack(extraAttributes.getString(s)))); + + + components.add(targetIndex, new CompactorPreviewTooltipComponent(slotAndItem, dimensions)); + components.add(targetIndex, TooltipComponent.of(Text.literal(" ").append( + Text.literal("Contents:").fillStyle(Style.EMPTY + .withItalic(true))) + .asOrderedText())); + if (attributesKeys.stream().anyMatch(s -> s.contains("PERSONAL_DELETOR_ACTIVE"))) { + MutableText isActiveText = Text.literal("Active: "); + if (extraAttributes.getBoolean("PERSONAL_DELETOR_ACTIVE")) { + components.add(targetIndex, TooltipComponent.of(isActiveText.append( + Text.literal("YES").fillStyle(Style.EMPTY.withBold(true).withColor(Formatting.GREEN)) + ).asOrderedText() + )); + } else { + components.add(targetIndex, TooltipComponent.of(isActiveText.append( + Text.literal("NO").fillStyle(Style.EMPTY.withBold(true).withColor(Formatting.RED)) + ).asOrderedText() + )); + } + } + context.invokeDrawTooltip(mcClient.textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); + return true; + } + + private static Integer getNumberAtEnd(String str, String attributesKey) { + try { + String numberPartOfTheString = str.replace(attributesKey, ""); + return Integer.parseInt(numberPartOfTheString); + } catch (NumberFormatException e) { + return 0; + } + } +} From 63f8b9fac7ecb5c37e32031cc6061cbd1c7612c5 Mon Sep 17 00:00:00 2001 From: vicisacat Date: Thu, 14 Sep 2023 15:55:35 +0200 Subject: [PATCH 4/5] "Moved BackpackPreview to new sub-package 'item'" Refactored code by moving the BackpackPreview class to a new 'item' sub-package. --- .../java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java | 2 +- .../skyblocker/skyblock/{ => item}/BackpackPreview.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/me/xmrvizzy/skyblocker/skyblock/{ => item}/BackpackPreview.java (99%) diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java index ddcbb33fd2..48b85dbe85 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java @@ -3,7 +3,7 @@ import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import me.xmrvizzy.skyblocker.mixin.accessor.DrawContextInvoker; -import me.xmrvizzy.skyblocker.skyblock.BackpackPreview; +import me.xmrvizzy.skyblocker.skyblock.item.BackpackPreview; import me.xmrvizzy.skyblocker.skyblock.experiment.ChronomatronSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.ExperimentSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.SuperpairsSolver; diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/BackpackPreview.java similarity index 99% rename from src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java rename to src/main/java/me/xmrvizzy/skyblocker/skyblock/item/BackpackPreview.java index f4615b52d7..dc8f77cdd9 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/BackpackPreview.java @@ -1,4 +1,4 @@ -package me.xmrvizzy.skyblocker.skyblock; +package me.xmrvizzy.skyblocker.skyblock.item; import com.mojang.blaze3d.systems.RenderSystem; import me.xmrvizzy.skyblocker.SkyblockerMod; From 3881303e47384cc0b619c9172fcef685f29a56ce Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Fri, 15 Sep 2023 00:18:36 -0400 Subject: [PATCH 5/5] Refactor CompactorDeletorPreview and add option --- .../skyblocker/config/SkyblockerConfig.java | 1 + .../skyblocker/mixin/HandledScreenMixin.java | 24 +-- .../mixin/accessor/DrawContextInvoker.java | 3 +- .../item/CompactorDeletorPreview.java | 140 +++++++----------- .../CompactorPreviewTooltipComponent.java | 48 +++--- .../assets/skyblocker/lang/en_us.json | 1 + 6 files changed, 92 insertions(+), 125 deletions(-) diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java index ca3b221a1f..d065ef70b5 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java @@ -145,6 +145,7 @@ public ItemData(String itemName) { public static class General { public boolean acceptReparty = true; public boolean backpackPreviewWithoutShift = false; + public boolean compactorDeletorPreview = true; public boolean hideEmptyTooltips = true; @ConfigEntry.Category("tabHud") diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java index 48b85dbe85..3353278873 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java @@ -2,12 +2,11 @@ import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; -import me.xmrvizzy.skyblocker.mixin.accessor.DrawContextInvoker; -import me.xmrvizzy.skyblocker.skyblock.item.BackpackPreview; import me.xmrvizzy.skyblocker.skyblock.experiment.ChronomatronSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.ExperimentSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.SuperpairsSolver; import me.xmrvizzy.skyblocker.skyblock.experiment.UltrasequencerSolver; +import me.xmrvizzy.skyblocker.skyblock.item.BackpackPreview; import me.xmrvizzy.skyblocker.skyblock.item.CompactorDeletorPreview; import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup; import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry; @@ -34,6 +33,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Map; +import java.util.regex.Matcher; @Mixin(HandledScreen.class) public abstract class HandledScreenMixin extends Screen { @@ -52,27 +52,30 @@ protected HandledScreenMixin(Text title) { } } - @SuppressWarnings("DataFlowIssue") // makes intellij be quiet about this.focusedSlot maybe being null. It's already null checked in mixined method. + @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) public void skyblocker$drawMouseOverTooltip(DrawContext context, int x, int y, CallbackInfo ci) { - ItemStack stack = this.focusedSlot.getStack(); - String internalName = ItemRegistry.getInternalName(stack); + if (!Utils.isOnSkyblock()) return; // Hide Empty Tooltips - if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.hideEmptyTooltips && this.focusedSlot != null && focusedSlot.getStack().getName().getString().equals(" ")) { + if (SkyblockerConfig.get().general.hideEmptyTooltips && focusedSlot.getStack().getName().getString().equals(" ")) { ci.cancel(); } // Backpack Preview boolean shiftDown = SkyblockerConfig.get().general.backpackPreviewWithoutShift ^ Screen.hasShiftDown(); - if (this.client == null || this.client.player == null) return; - if (shiftDown && this.getTitle().getString().equals("Storage") && this.focusedSlot.inventory != this.client.player.getInventory() && BackpackPreview.renderPreview(context, this.focusedSlot.getIndex(), x, y)) { + if (shiftDown && getTitle().getString().equals("Storage") && focusedSlot.inventory != client.player.getInventory() && BackpackPreview.renderPreview(context, focusedSlot.getIndex(), x, y)) { ci.cancel(); } // Compactor Preview - if ((internalName.contains("PERSONAL_COMPACTOR_") || internalName.contains("PERSONAL_DELETOR_")) && CompactorDeletorPreview.displayCompactorDeletorPreview((DrawContextInvoker) context, x, y, stack)) { - ci.cancel(); + if (SkyblockerConfig.get().general.compactorDeletorPreview) { + ItemStack stack = focusedSlot.getStack(); + Matcher matcher = CompactorDeletorPreview.NAME.matcher(ItemRegistry.getInternalName(stack)); + if (matcher.matches() && CompactorDeletorPreview.drawPreview(context, stack, matcher.group("type"), matcher.group("size"), x, y)) { + ci.cancel(); + } } } @@ -87,7 +90,6 @@ protected HandledScreenMixin(Text title) { } - @Unique private ItemStack skyblocker$experimentSolvers$getStack(Slot slot, ItemStack stack) { ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver(); diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/DrawContextInvoker.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/DrawContextInvoker.java index 55ef077475..f1e5b684fc 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/DrawContextInvoker.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/accessor/DrawContextInvoker.java @@ -12,7 +12,6 @@ @Mixin(DrawContext.class) public interface DrawContextInvoker { - @SuppressWarnings("unused") - @Invoker("drawTooltip") + @Invoker void invokeDrawTooltip(TextRenderer textRenderer, List components, int x, int y, TooltipPositioner positioner); } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorDeletorPreview.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorDeletorPreview.java index 70a37b8aeb..7b93fe1ed9 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorDeletorPreview.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorDeletorPreview.java @@ -1,122 +1,92 @@ package me.xmrvizzy.skyblocker.skyblock.item; +import it.unimi.dsi.fastutil.ints.IntIntPair; +import it.unimi.dsi.fastutil.ints.IntObjectPair; import me.xmrvizzy.skyblocker.mixin.accessor.DrawContextInvoker; import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.tooltip.HoveredTooltipPositioner; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.MutableText; -import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; public class CompactorDeletorPreview { - - private static final MinecraftClient mcClient = MinecraftClient.getInstance(); - private static final Map personalCompactorTypeToSlot = new HashMap<>(); - // Lines, and slots per lines - static { - personalCompactorTypeToSlot.put("4000", new int[]{1,1}); - personalCompactorTypeToSlot.put("5000", new int[]{1,3}); - personalCompactorTypeToSlot.put("6000", new int[]{1,7}); - personalCompactorTypeToSlot.put("7000", new int[]{2,6}); - personalCompactorTypeToSlot.put("default", new int[]{1,6}); - } - - public static boolean displayCompactorDeletorPreview(DrawContextInvoker context, int x, int y, ItemStack stack) { - String internalName = ItemRegistry.getInternalName(stack); - - String prefix; - String itemSlotPrefix; - if (internalName.contains("PERSONAL_COMPACTOR_")) { - prefix = "PERSONAL_COMPACTOR_"; - itemSlotPrefix = "personal_compact_"; - } else { - prefix = "PERSONAL_DELETOR_"; - itemSlotPrefix = "personal_deletor_"; - } - - // Find the line to insert component - int targetIndex = -1; - int lineCount = 0; - - List tooltips = Screen.getTooltipFromItem(mcClient, stack); - for (int i = 0; i < tooltips.size(); i++) { - if (tooltips.get(i).getString().isEmpty()) { - lineCount += 1; - } - if (lineCount == 2) { - targetIndex = i; - break; - } - } + /** + * The width and height in slots of the compactor/deletor + */ + private static final Map DIMENSIONS = Map.of( + "4000", IntIntPair.of(1, 1), + "5000", IntIntPair.of(1, 3), + "6000", IntIntPair.of(1, 7), + "7000", IntIntPair.of(2, 6) + ); + private static final IntIntPair DEFAULT_DIMENSION = IntIntPair.of(1, 6); + public static final Pattern NAME = Pattern.compile("PERSONAL_(?COMPACTOR|DELETOR)_(?\\d+)"); + private static final MinecraftClient client = MinecraftClient.getInstance(); + + public static boolean drawPreview(DrawContext context, ItemStack stack, String type, String size, int x, int y) { + List tooltips = Screen.getTooltipFromItem(client, stack); + int targetIndex = getTargetIndex(tooltips); if (targetIndex == -1) return false; - List components = new java.util.ArrayList<>(tooltips.stream().map(Text::asOrderedText).map(TooltipComponent::of).toList()); - - // STUFF - String internalID = ItemRegistry.getInternalName(stack); - String compactorType = internalID.replaceFirst(prefix, ""); - int[] dimensions = personalCompactorTypeToSlot.containsKey(compactorType) ? personalCompactorTypeToSlot.get(compactorType) : personalCompactorTypeToSlot.get("default"); + // Get items in compactor or deletor NbtCompound nbt = stack.getNbt(); if (nbt == null || !nbt.contains("ExtraAttributes", 10)) { return false; } NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); - Set attributesKeys = extraAttributes.getKeys(); - List compactorItems = attributesKeys.stream().filter(s -> s.contains(itemSlotPrefix)).toList(); - Map slotAndItem = new HashMap<>(); + // Get the slots and their items from the nbt, which is in the format personal_compact_ or personal_deletor_ + List> slots = extraAttributes.getKeys().stream().filter(slot -> slot.contains(type.toLowerCase().substring(0, 7))).map(slot -> IntObjectPair.of(Integer.parseInt(slot.substring(17)), ItemRegistry.getItemStack(extraAttributes.getString(slot)))).toList(); + + List components = tooltips.stream().map(Text::asOrderedText).map(TooltipComponent::of).collect(Collectors.toList()); + IntIntPair dimensions = DIMENSIONS.getOrDefault(size, DEFAULT_DIMENSION); - if (compactorItems.isEmpty()) { - int slotsCount = (dimensions[0] * dimensions[1]); - components.add(targetIndex, TooltipComponent.of(Text.literal( - slotsCount + (slotsCount == 1 ? " slot": " slots")) - .fillStyle(Style.EMPTY.withColor(Formatting.DARK_GRAY)).asOrderedText())); + // If there are no items in compactor or deletor + if (slots.isEmpty()) { + int slotsCount = dimensions.leftInt() * dimensions.rightInt(); + components.add(targetIndex, TooltipComponent.of(Text.literal(slotsCount + (slotsCount == 1 ? " slot" : " slots")).formatted(Formatting.GRAY).asOrderedText())); - context.invokeDrawTooltip(mcClient.textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); + ((DrawContextInvoker) context).invokeDrawTooltip(client.textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); return true; } - compactorItems.forEach(s -> slotAndItem.put(getNumberAtEnd(s, itemSlotPrefix), ItemRegistry.getItemStack(extraAttributes.getString(s)))); + // Add the preview tooltip component + components.add(targetIndex, new CompactorPreviewTooltipComponent(slots, dimensions)); - - components.add(targetIndex, new CompactorPreviewTooltipComponent(slotAndItem, dimensions)); - components.add(targetIndex, TooltipComponent.of(Text.literal(" ").append( - Text.literal("Contents:").fillStyle(Style.EMPTY - .withItalic(true))) - .asOrderedText())); - if (attributesKeys.stream().anyMatch(s -> s.contains("PERSONAL_DELETOR_ACTIVE"))) { - MutableText isActiveText = Text.literal("Active: "); - if (extraAttributes.getBoolean("PERSONAL_DELETOR_ACTIVE")) { - components.add(targetIndex, TooltipComponent.of(isActiveText.append( - Text.literal("YES").fillStyle(Style.EMPTY.withBold(true).withColor(Formatting.GREEN)) - ).asOrderedText() - )); - } else { - components.add(targetIndex, TooltipComponent.of(isActiveText.append( - Text.literal("NO").fillStyle(Style.EMPTY.withBold(true).withColor(Formatting.RED)) - ).asOrderedText() - )); - } + // Render accompanying text + components.add(targetIndex, TooltipComponent.of(Text.literal("Contents:").asOrderedText())); + if (extraAttributes.contains("PERSONAL_DELETOR_ACTIVE")) { + components.add(targetIndex, TooltipComponent.of(Text.literal("Active: ") + .append(extraAttributes.getBoolean("PERSONAL_DELETOR_ACTIVE") ? Text.literal("YES").formatted(Formatting.BOLD).formatted(Formatting.GREEN) : Text.literal("NO").formatted(Formatting.BOLD).formatted(Formatting.RED)).asOrderedText())); } - context.invokeDrawTooltip(mcClient.textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); + ((DrawContextInvoker) context).invokeDrawTooltip(client.textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE); return true; } - private static Integer getNumberAtEnd(String str, String attributesKey) { - try { - String numberPartOfTheString = str.replace(attributesKey, ""); - return Integer.parseInt(numberPartOfTheString); - } catch (NumberFormatException e) { - return 0; + /** + * Finds the target index to insert the preview component, which is the second empty line + */ + private static int getTargetIndex(List tooltips) { + int targetIndex = -1; + int lineCount = 0; + for (int i = 0; i < tooltips.size(); i++) { + if (tooltips.get(i).getString().isEmpty()) { + lineCount += 1; + } + if (lineCount == 2) { + targetIndex = i; + break; + } } + return targetIndex; } } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorPreviewTooltipComponent.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorPreviewTooltipComponent.java index e916a94b5f..45e3c6356d 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorPreviewTooltipComponent.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/item/CompactorPreviewTooltipComponent.java @@ -1,60 +1,54 @@ package me.xmrvizzy.skyblocker.skyblock.item; +import it.unimi.dsi.fastutil.ints.IntIntPair; +import it.unimi.dsi.fastutil.ints.IntObjectPair; import me.xmrvizzy.skyblocker.SkyblockerMod; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; -import java.util.Map; - public class CompactorPreviewTooltipComponent implements TooltipComponent { - private static final Identifier INVENTORY_TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/inventory_background.png"); + private final Iterable> items; + private final IntIntPair dimensions; - Map items; - int[] dimensions; - - public CompactorPreviewTooltipComponent(Map items, int[] dimensions) { + public CompactorPreviewTooltipComponent(Iterable> items, IntIntPair dimensions) { this.items = items; this.dimensions = dimensions; } + @Override public int getHeight() { - return dimensions[0] * 18 + 14; + return dimensions.leftInt() * 18 + 14; } @Override public int getWidth(TextRenderer textRenderer) { - return dimensions[1] * 18 + 14; + return dimensions.rightInt() * 18 + 14; } @Override public void drawItems(TextRenderer textRenderer, int x, int y, DrawContext context) { - context.drawTexture(INVENTORY_TEXTURE, x, y, 0, 0, 7 + dimensions[1] * 18, 7); - context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions[1] * 18, y, 169, 0, 7, 7); + context.drawTexture(INVENTORY_TEXTURE, x, y, 0, 0, 7 + dimensions.rightInt() * 18, 7); + context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions.rightInt() * 18, y, 169, 0, 7, 7); - for (int i = 0; i < dimensions[0]; i++) { + for (int i = 0; i < dimensions.leftInt(); i++) { context.drawTexture(INVENTORY_TEXTURE, x, y + 7 + i * 18, 0, 7, 7, 18); - for (int j = 0; j < dimensions[1]; j++) { + for (int j = 0; j < dimensions.rightInt(); j++) { context.drawTexture(INVENTORY_TEXTURE, x + 7 + j * 18, y + 7 + i * 18, 7, 7, 18, 18); } - context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions[1] * 18, y + 7 + i * 18, 169, 7, 7, 18); + context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions.rightInt() * 18, y + 7 + i * 18, 169, 7, 7, 18); } - context.drawTexture(INVENTORY_TEXTURE, x, y + 7 + dimensions[0] * 18, 0, 25, 7 + dimensions[1] * 18, 7); - context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions[1] * 18, y + 7 + dimensions[0] * 18, 169, 25, 7, 7); - - MatrixStack matrices = context.getMatrices(); - for (Integer i : items.keySet()) { - int itemX = x + i % dimensions[1] * 18 + 8; - int itemY = y + i / dimensions[1] * 18 + 8; - matrices.push(); - matrices.translate(0, 0, 200); - context.drawItem(items.get(i), itemX, itemY); - context.drawItemInSlot(textRenderer, items.get(i), itemX, itemY); - matrices.pop(); + context.drawTexture(INVENTORY_TEXTURE, x, y + 7 + dimensions.leftInt() * 18, 0, 25, 7 + dimensions.rightInt() * 18, 7); + context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions.rightInt() * 18, y + 7 + dimensions.leftInt() * 18, 169, 25, 7, 7); + + for (IntObjectPair entry : items) { + int itemX = x + entry.leftInt() % dimensions.rightInt() * 18 + 8; + int itemY = y + entry.leftInt() / dimensions.rightInt() * 18 + 8; + context.drawItem(entry.right(), itemX, itemY); + context.drawItemInSlot(textRenderer, entry.right(), itemX, itemY); } } } diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index ffcb4e818d..fb41b7a13e 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -42,6 +42,7 @@ "text.autoconfig.skyblocker.option.general.quiverWarning.enableQuiverWarningInDungeons": "Enable Quiver Warning In Dungeons", "text.autoconfig.skyblocker.option.general.quiverWarning.enableQuiverWarningAfterDungeon": "Enable Quiver Warning After a Dungeon", "text.autoconfig.skyblocker.option.general.backpackPreviewWithoutShift": "View backpack preview without holding Shift", + "text.autoconfig.skyblocker.option.general.compactorDeletorPreview": "Enable Compactor/Deletor Preview", "text.autoconfig.skyblocker.option.general.tabHud": "Fancy tab HUD", "text.autoconfig.skyblocker.option.general.tabHud.tabHudEnabled": "Enable fancy tab HUD", "text.autoconfig.skyblocker.option.general.tabHud.tabHudScale": "Scale factor of fancy tab HUD",