From 138e01daeb495f67a4d5dfd9ef66e9448951b508 Mon Sep 17 00:00:00 2001 From: noramibuu Date: Sat, 4 Oct 2025 16:43:06 +0300 Subject: [PATCH 01/13] display food information --- .../systems/modules/render/BetterTooltips.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index 06fe0da2fa..9ce8277248 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -156,6 +156,14 @@ public class BetterTooltips extends Module { .build() ); + private final Setting foodInfo = sgPreviews.add(new BoolSetting.Builder() + .name("food-info") + .description("Shows hunger and saturation values for food items.") + .defaultValue(true) + .onChanged(value -> updateTooltips = true) + .build() + ); + // Extras public final Setting byteSize = sgOther.add(new BoolSetting.Builder() @@ -236,6 +244,16 @@ private void appendTooltip(ItemStackTooltipEvent event) { } } + // Food info + if (foodInfo.get()) { + FoodComponent food = event.itemStack().get(DataComponentTypes.FOOD); + if (food != null) { + // Those emojis really look like in-game hunger bar + event.appendStart(Text.literal(String.format("🍖 %d (💛 %.1f)", food.nutrition(), food.saturation())) + .formatted(Formatting.GRAY)); + } + } + // Item size tooltip if (byteSize.get()) { switch (ItemStack.CODEC.encodeStart(mc.player.getRegistryManager().getOps(NbtOps.INSTANCE), event.itemStack())) { From 2d99d8fbb54eb232d6e0204c14163c1f267cee39 Mon Sep 17 00:00:00 2001 From: noramibuu Date: Sat, 4 Oct 2025 18:21:07 +0300 Subject: [PATCH 02/13] display bundle data --- .../meteorclient/mixin/ItemStackMixin.java | 18 +++ .../modules/render/BetterTooltips.java | 31 ++++- .../utils/tooltip/BundleTooltipComponent.java | 110 ++++++++++++++++++ 3 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ItemStackMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ItemStackMixin.java index 21b7729b39..4a63914480 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ItemStackMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ItemStackMixin.java @@ -10,9 +10,12 @@ import meteordevelopment.meteorclient.events.entity.player.FinishUsingItemEvent; import meteordevelopment.meteorclient.events.entity.player.StoppedUsingItemEvent; import meteordevelopment.meteorclient.events.game.ItemStackTooltipEvent; +import meteordevelopment.meteorclient.events.render.TooltipDataEvent; import meteordevelopment.meteorclient.utils.Utils; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.tooltip.TooltipData; import net.minecraft.text.Text; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; @@ -22,6 +25,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; +import java.util.Optional; import static meteordevelopment.meteorclient.MeteorClient.mc; @@ -37,6 +41,20 @@ private List onGetTooltip(List original) { return original; } + @ModifyReturnValue(method = "getTooltipData", at = @At("RETURN")) + private Optional onGetTooltipData(Optional original) { + ItemStack stack = (ItemStack) (Object) this; + + if (stack.getItem() instanceof net.minecraft.item.BundleItem) { + TooltipDataEvent event = MeteorClient.EVENT_BUS.post(TooltipDataEvent.get(stack)); + if (event.tooltipData != null) { + return Optional.of(event.tooltipData); + } + } + + return original; + } + @Inject(method = "finishUsing", at = @At("HEAD")) private void onFinishUsing(World world, LivingEntity user, CallbackInfoReturnable info) { if (user == mc.player) { diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index 9ce8277248..a2b84efe3a 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -156,6 +156,14 @@ public class BetterTooltips extends Module { .build() ); + private final Setting bundles = sgPreviews.add(new BoolSetting.Builder() + .name("bundles") + .description("Shows a preview of bundle contents when hovering over it in an inventory.") + .defaultValue(true) + .onChanged(value -> updateTooltips = true) + .build() + ); + private final Setting foodInfo = sgPreviews.add(new BoolSetting.Builder() .name("food-info") .description("Shows hunger and saturation values for food items.") @@ -248,12 +256,13 @@ private void appendTooltip(ItemStackTooltipEvent event) { if (foodInfo.get()) { FoodComponent food = event.itemStack().get(DataComponentTypes.FOOD); if (food != null) { - // Those emojis really look like in-game hunger bar + // Those emojis really look like in-game hunger bar event.appendStart(Text.literal(String.format("🍖 %d (💛 %.1f)", food.nutrition(), food.saturation())) .formatted(Formatting.GRAY)); } } + // Item size tooltip if (byteSize.get()) { switch (ItemStack.CODEC.encodeStart(mc.player.getRegistryManager().getOps(NbtOps.INSTANCE), event.itemStack())) { @@ -346,6 +355,21 @@ else if (event.itemStack.getItem() instanceof EntityBucketItem bucketItem && pre event.tooltipData = new EntityTooltipComponent(entity); } } + + // Bundle preview + else if (event.itemStack.getItem() instanceof BundleItem && previewBundles()) { + if (event.itemStack.contains(DataComponentTypes.BUNDLE_CONTENTS)) { + BundleContentsComponent bundleContents = event.itemStack.get(DataComponentTypes.BUNDLE_CONTENTS); + if (bundleContents != null && !bundleContents.isEmpty()) { + ItemStack[] bundleItems = new ItemStack[bundleContents.size()]; + int index = 0; + for (ItemStack stack : bundleContents.iterate()) { + bundleItems[index++] = stack; + } + event.tooltipData = new BundleTooltipComponent(bundleItems, bundleContents, new Color(139, 69, 19, 255)); + } + } + } } public void applyCompactShulkerTooltip(List stacks, Consumer textConsumer) { @@ -377,6 +401,7 @@ private void appendPreviewTooltipText(ItemStackTooltipEvent event, boolean space || (event.itemStack().getItem() == Items.WRITABLE_BOOK && books.get()) || (event.itemStack().getItem() == Items.WRITTEN_BOOK && books.get()) || (event.itemStack().getItem() instanceof EntityBucketItem && entitiesInBuckets.get()) + || (event.itemStack().getItem() instanceof BundleItem && bundles.get()) || (event.itemStack().getItem() instanceof BannerItem && banners.get()) || (event.itemStack().contains(DataComponentTypes.PROVIDES_BANNER_PATTERNS) && banners.get()) || (event.itemStack().getItem() == Items.SHIELD && banners.get()) @@ -460,6 +485,10 @@ private boolean previewEntities() { return isPressed() && entitiesInBuckets.get(); } + private boolean previewBundles() { + return isPressed() && bundles.get(); + } + private boolean isPressed() { return (keybind.get().isPressed() && displayWhen.get() == DisplayWhen.Keybind) || displayWhen.get() == DisplayWhen.Always; } diff --git a/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java b/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java new file mode 100644 index 0000000000..41f5e3b30e --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java @@ -0,0 +1,110 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.utils.tooltip; + +import meteordevelopment.meteorclient.utils.render.color.Color; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.component.type.BundleContentsComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Colors; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; +import org.apache.commons.lang3.math.Fraction; + +public class BundleTooltipComponent implements TooltipComponent, MeteorTooltipData { + private static final Identifier BUNDLE_SLOT_BACKGROUND_TEXTURE = Identifier.ofVanilla("container/bundle/slot_background"); + private static final Identifier BUNDLE_PROGRESS_BAR_BORDER_TEXTURE = Identifier.ofVanilla("container/bundle/bundle_progressbar_border"); + private static final Identifier BUNDLE_PROGRESS_BAR_FILL_TEXTURE = Identifier.ofVanilla("container/bundle/bundle_progressbar_fill"); + private static final Identifier BUNDLE_PROGRESS_BAR_FULL_TEXTURE = Identifier.ofVanilla("container/bundle/bundle_progressbar_full"); + + private static final int SLOTS_PER_ROW = 8; + private static final int SLOT_DIMENSION = 24; + private static final int ROW_WIDTH = 8 + SLOTS_PER_ROW * SLOT_DIMENSION + 8; + private static final int PROGRESS_BAR_WIDTH = 94; + private static final int PROGRESS_BAR_HEIGHT = 13; + private static final Text BUNDLE_FULL = Text.translatable("item.minecraft.bundle.full"); + + private final ItemStack[] items; + private final BundleContentsComponent bundleContents; + private final int width; + private final int height; + + public BundleTooltipComponent(ItemStack[] items, BundleContentsComponent bundleContents, Color color) { + this.items = items; + this.bundleContents = bundleContents; + + int rows = (items.length + SLOTS_PER_ROW - 1) / SLOTS_PER_ROW; + this.width = ROW_WIDTH; + this.height = 8 + rows * SLOT_DIMENSION + 8 + PROGRESS_BAR_HEIGHT + 4; + } + + @Override + public TooltipComponent getComponent() { + return this; + } + + @Override + public int getHeight(TextRenderer textRenderer) { + return height; + } + + @Override + public int getWidth(TextRenderer textRenderer) { + return width; + } + + @Override + public void drawItems(TextRenderer textRenderer, int x, int y, int width, int height, DrawContext context) { + int row = 0; + int col = 0; + + for (ItemStack itemStack : items) { + if (!itemStack.isEmpty()) { + int slotX = x + 8 + col * SLOT_DIMENSION; + int slotY = y + 8 + row * SLOT_DIMENSION; + + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, BUNDLE_SLOT_BACKGROUND_TEXTURE, slotX, slotY, SLOT_DIMENSION, SLOT_DIMENSION); + + context.drawItem(itemStack, slotX + 4, slotY + 4, 0); + context.drawStackOverlay(textRenderer, itemStack, slotX + 4, slotY + 4); + } + + col++; + if (col >= SLOTS_PER_ROW) { + col = 0; + row++; + } + } + + int progressBarX = x + (this.width - PROGRESS_BAR_WIDTH) / 2; + int progressBarY = y + this.height - PROGRESS_BAR_HEIGHT - 4; + drawProgressBar(progressBarX, progressBarY, textRenderer, context); + } + + private void drawProgressBar(int x, int y, TextRenderer textRenderer, DrawContext context) { + int fillAmount = MathHelper.clamp(MathHelper.multiplyFraction(bundleContents.getOccupancy(), PROGRESS_BAR_WIDTH), 0, PROGRESS_BAR_WIDTH); + + Identifier fillTexture = bundleContents.getOccupancy().compareTo(Fraction.ONE) >= 0 + ? BUNDLE_PROGRESS_BAR_FULL_TEXTURE + : BUNDLE_PROGRESS_BAR_FILL_TEXTURE; + + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, fillTexture, x + 1, y, fillAmount, PROGRESS_BAR_HEIGHT); + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, BUNDLE_PROGRESS_BAR_BORDER_TEXTURE, x, y, PROGRESS_BAR_WIDTH, PROGRESS_BAR_HEIGHT); + + Text label = getProgressBarLabel(); + if (label != null) { + context.drawCenteredTextWithShadow(textRenderer, label, x + PROGRESS_BAR_WIDTH / 2, y + 3, Colors.WHITE); + } + } + + private Text getProgressBarLabel() { + return bundleContents.getOccupancy().compareTo(Fraction.ONE) >= 0 ? BUNDLE_FULL : null; + } +} From fe1dcd011d944e620fc5891f2c7f55471c23b928 Mon Sep 17 00:00:00 2001 From: noramibuu Date: Sat, 4 Oct 2025 21:37:44 +0300 Subject: [PATCH 03/13] implement open container --- .../gui/screens/ContainerInventoryScreen.java | 142 ++++++++++++++++++ .../modules/render/BetterTooltips.java | 29 +++- 2 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java diff --git a/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java new file mode 100644 index 0000000000..c51dc98f06 --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java @@ -0,0 +1,142 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.gui.screens; + +import meteordevelopment.meteorclient.utils.Utils; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.BundleContentsComponent; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.BundleItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.tooltip.TooltipType; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +import java.util.ArrayList; +import java.util.List; + +/* + * i couldn't figure out how to add proper outer borders for the GUI without adding custom textures. @TODO + */ +public class ContainerInventoryScreen extends Screen { + private static final Identifier SLOT_TEXTURE = Identifier.ofVanilla("container/slot"); + private static final int SLOT_SIZE = 18; + private static final int SCREEN_WIDTH = 176; + + private final List containerItems; + private final PlayerInventory playerInventory; + private final int containerRows; + private final Item.TooltipContext tooltipContext; + private int x, y; + + public ContainerInventoryScreen(ItemStack containerItem) { + super(containerItem.getName()); + this.playerInventory = mc.player.getInventory(); + this.tooltipContext = Item.TooltipContext.create(mc.world); + + this.containerItems = new ArrayList<>(); + if (containerItem.getItem() instanceof BundleItem) { + BundleContentsComponent bundleContents = containerItem.get(DataComponentTypes.BUNDLE_CONTENTS); + if (bundleContents != null) { + bundleContents.iterate().forEach(containerItems::add); + } + } else { + ItemStack[] tempItems = new ItemStack[64]; + Utils.getItemsInContainerItem(containerItem, tempItems); + for (ItemStack stack : tempItems) { + if (stack != null && !stack.isEmpty()) { + containerItems.add(stack); + } + } + } + + this.containerRows = Math.max(1, (containerItems.size() + 8) / 9); + } + + @Override + protected void init() { + super.init(); + this.x = (this.width - SCREEN_WIDTH) / 2; + this.y = (this.height - (114 + containerRows * SLOT_SIZE + 20)) / 2; + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + super.render(context, mouseX, mouseY, delta); + + int baseX = x + 8; + int baseY = y + 18; + int playerY = baseY + containerRows * SLOT_SIZE + 20; + + for (int row = 0; row < containerRows + 4; row++) { + for (int col = 0; col < 9; col++) { + int slotY = row < containerRows ? baseY + row * SLOT_SIZE : playerY + (row - containerRows) * SLOT_SIZE; + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, SLOT_TEXTURE, baseX + col * SLOT_SIZE, slotY, SLOT_SIZE, SLOT_SIZE); + } + } + + for (int i = 0; i < containerItems.size(); i++) { + ItemStack item = containerItems.get(i); + if (!item.isEmpty()) { + int itemX = baseX + (i % 9) * SLOT_SIZE + 1; + int itemY = baseY + (i / 9) * SLOT_SIZE + 1; + context.drawItem(item, itemX, itemY); + context.drawStackOverlay(textRenderer, item, itemX, itemY); + } + } + + for (int row = 0; row < 4; row++) { + for (int col = 0; col < 9; col++) { + int slotIndex = row < 3 ? 9 + row * 9 + col : col; + ItemStack item = playerInventory.getStack(slotIndex); + if (!item.isEmpty()) { + int itemX = baseX + col * SLOT_SIZE + 1; + int itemY = playerY + row * SLOT_SIZE + 1; + context.drawItem(item, itemX, itemY); + context.drawStackOverlay(textRenderer, item, itemX, itemY); + } + } + } + + context.getMatrices().pushMatrix(); + context.getMatrices().translate((float)x, (float)y); + if (textRenderer != null) { + context.drawText(textRenderer, title != null && !title.getString().isEmpty() ? title : Text.literal("Container"), 8, 6, -12566464, false); + context.drawText(textRenderer, playerInventory.getDisplayName(), 8, 18 + containerRows * SLOT_SIZE + 10, -12566464, false); + } + context.getMatrices().popMatrix(); + + if (mouseX >= baseX && mouseX < baseX + 9 * SLOT_SIZE) { + int col = (mouseX - baseX) / SLOT_SIZE; + + if (mouseY >= baseY && mouseY < baseY + containerRows * SLOT_SIZE) { + int index = ((mouseY - baseY) / SLOT_SIZE) * 9 + col; + if (index < containerItems.size()) { + ItemStack item = containerItems.get(index); + if (!item.isEmpty()) { + context.drawTooltip(textRenderer, item.getTooltip(tooltipContext, mc.player, TooltipType.BASIC), item.getTooltipData(), mouseX, mouseY); + } + } + } else if (mouseY >= playerY && mouseY < playerY + 4 * SLOT_SIZE) { + int row = (mouseY - playerY) / SLOT_SIZE; + int slotIndex = row < 3 ? 9 + row * 9 + col : col; + if (slotIndex < playerInventory.size()) { + ItemStack item = playerInventory.getStack(slotIndex); + if (!item.isEmpty()) { + context.drawTooltip(textRenderer, item.getTooltip(tooltipContext, mc.player, TooltipType.BASIC), item.getTooltipData(), mouseX, mouseY); + } + } + } + } + } + +} diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index a2b84efe3a..9f0d8b35ab 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -10,6 +10,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import meteordevelopment.meteorclient.events.game.ItemStackTooltipEvent; import meteordevelopment.meteorclient.events.render.TooltipDataEvent; +import meteordevelopment.meteorclient.gui.screens.ContainerInventoryScreen; import meteordevelopment.meteorclient.mixin.EntityAccessor; import meteordevelopment.meteorclient.mixin.EntityBucketItemAccessor; import meteordevelopment.meteorclient.settings.*; @@ -23,6 +24,7 @@ import meteordevelopment.meteorclient.utils.tooltip.*; import meteordevelopment.orbit.EventHandler; import net.minecraft.component.DataComponentTypes; + import net.minecraft.component.type.*; import net.minecraft.component.type.SuspiciousStewEffectsComponent.StewEffect; import net.minecraft.entity.Bucketable; @@ -47,6 +49,7 @@ import java.util.function.Consumer; import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_ALT; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT; public class BetterTooltips extends Module { public static final Color ECHEST_COLOR = new Color(0, 50, 50); @@ -74,6 +77,13 @@ public class BetterTooltips extends Module { .build() ); + private final Setting openInventoryKey = sgGeneral.add(new KeybindSetting.Builder() + .name("open-inventory") + .description("Key to open full container inventory screen.") + .defaultValue(Keybind.fromKey(GLFW_KEY_LEFT_SHIFT)) + .build() + ); + private final Setting middleClickOpen = sgGeneral.add(new BoolSetting.Builder() .name("middle-click-open") .description("Opens a GUI window with the inventory of the storage block or book when you middle click the item.") @@ -296,6 +306,10 @@ private void appendTooltip(ItemStackTooltipEvent event) { } } + if (openInventoryKey.get().isPressed() && (Utils.hasItems(event.itemStack()) || event.itemStack().getItem() instanceof BundleItem)) { + mc.setScreen(new ContainerInventoryScreen(event.itemStack())); + } + // Hold to preview tooltip appendPreviewTooltipText(event, true); } @@ -394,7 +408,7 @@ public void applyCompactShulkerTooltip(List stacks, Consumer te } private void appendPreviewTooltipText(ItemStackTooltipEvent event, boolean spacer) { - if (!isPressed() && ( + boolean showPreviewText = !isPressed() && ( shulkers.get() && Utils.hasItems(event.itemStack()) || (event.itemStack().getItem() == Items.ENDER_CHEST && echest.get()) || (event.itemStack().getItem() == Items.FILLED_MAP && maps.get()) @@ -405,11 +419,22 @@ private void appendPreviewTooltipText(ItemStackTooltipEvent event, boolean space || (event.itemStack().getItem() instanceof BannerItem && banners.get()) || (event.itemStack().contains(DataComponentTypes.PROVIDES_BANNER_PATTERNS) && banners.get()) || (event.itemStack().getItem() == Items.SHIELD && banners.get()) - )) { + ); + + boolean showInventoryText = !openInventoryKey.get().isPressed() && ( + Utils.hasItems(event.itemStack()) || event.itemStack().getItem() instanceof BundleItem + ); + + if (showPreviewText) { // we don't want to add the spacer if the tooltip is hidden if (spacer) event.appendEnd(Text.literal("")); event.appendEnd(Text.literal("Hold " + Formatting.YELLOW + keybind + Formatting.RESET + " to preview")); } + + if (showInventoryText) { + if (spacer && !showPreviewText) event.appendEnd(Text.literal("")); + event.appendEnd(Text.literal("Hold " + Formatting.YELLOW + openInventoryKey.get() + Formatting.RESET + " to open inventory")); + } } private MutableText getStatusText(StatusEffectInstance effect) { From 45e2ab40845788a5cd6de65465ddc9beae0ef937 Mon Sep 17 00:00:00 2001 From: noramibuu Date: Sat, 4 Oct 2025 22:20:50 +0300 Subject: [PATCH 04/13] simplify food info --- .../systems/modules/render/BetterTooltips.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index 9f0d8b35ab..37741489e1 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -263,16 +263,12 @@ private void appendTooltip(ItemStackTooltipEvent event) { } // Food info - if (foodInfo.get()) { + if (foodInfo.get() && event.itemStack().contains(DataComponentTypes.FOOD)) { FoodComponent food = event.itemStack().get(DataComponentTypes.FOOD); - if (food != null) { - // Those emojis really look like in-game hunger bar - event.appendStart(Text.literal(String.format("🍖 %d (💛 %.1f)", food.nutrition(), food.saturation())) - .formatted(Formatting.GRAY)); - } + // Those emojis really look like in-game hunger bar + event.appendStart(Text.literal(String.format("🍖 %d hunger (💛 %.1f saturation)", food.nutrition(), food.saturation())).formatted(Formatting.GRAY)); } - // Item size tooltip if (byteSize.get()) { switch (ItemStack.CODEC.encodeStart(mc.player.getRegistryManager().getOps(NbtOps.INSTANCE), event.itemStack())) { From 88a9f6b4b544bd7b131c87260caf89060aae1f13 Mon Sep 17 00:00:00 2001 From: noramibuu Date: Sat, 4 Oct 2025 22:26:42 +0300 Subject: [PATCH 05/13] change default keybind to left ctrl instead of shift --- .../meteorclient/systems/modules/render/BetterTooltips.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index 37741489e1..5aa74a22f6 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -49,7 +49,7 @@ import java.util.function.Consumer; import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_ALT; -import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_CONTROL; public class BetterTooltips extends Module { public static final Color ECHEST_COLOR = new Color(0, 50, 50); @@ -80,7 +80,7 @@ public class BetterTooltips extends Module { private final Setting openInventoryKey = sgGeneral.add(new KeybindSetting.Builder() .name("open-inventory") .description("Key to open full container inventory screen.") - .defaultValue(Keybind.fromKey(GLFW_KEY_LEFT_SHIFT)) + .defaultValue(Keybind.fromKey(GLFW_KEY_LEFT_CONTROL)) .build() ); From a947abc10f2ce2a22be57c8c8c98e4134dd358d7 Mon Sep 17 00:00:00 2001 From: noramibuu Date: Sat, 4 Oct 2025 23:03:45 +0300 Subject: [PATCH 06/13] implement book view and rename openinv to view content --- .../modules/render/BetterTooltips.java | 54 +++++++++++++++---- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index 5aa74a22f6..3ec3d58547 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -23,8 +23,10 @@ import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.tooltip.*; import meteordevelopment.orbit.EventHandler; -import net.minecraft.component.DataComponentTypes; +import net.minecraft.client.gui.screen.ingame.BookScreen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.*; import net.minecraft.component.type.SuspiciousStewEffectsComponent.StewEffect; import net.minecraft.entity.Bucketable; @@ -77,10 +79,19 @@ public class BetterTooltips extends Module { .build() ); - private final Setting openInventoryKey = sgGeneral.add(new KeybindSetting.Builder() - .name("open-inventory") - .description("Key to open full container inventory screen.") + private final Setting viewContent = sgGeneral.add(new BoolSetting.Builder() + .name("view-content") + .description("Enable view content functionality.") + .defaultValue(true) + .onChanged(value -> updateTooltips = true) + .build() + ); + + private final Setting viewContentKey = sgGeneral.add(new KeybindSetting.Builder() + .name("view-content-key") + .description("Key to view contents (containers, books, etc.).") .defaultValue(Keybind.fromKey(GLFW_KEY_LEFT_CONTROL)) + .visible(() -> viewContent.get()) .build() ); @@ -302,8 +313,16 @@ private void appendTooltip(ItemStackTooltipEvent event) { } } - if (openInventoryKey.get().isPressed() && (Utils.hasItems(event.itemStack()) || event.itemStack().getItem() instanceof BundleItem)) { - mc.setScreen(new ContainerInventoryScreen(event.itemStack())); + if (viewContent.get() && viewContentKey.get().isPressed()) { + if (Utils.hasItems(event.itemStack()) || event.itemStack().getItem() instanceof BundleItem) { + if (mc.currentScreen instanceof HandledScreen) + mc.currentScreen.close(); + mc.setScreen(new ContainerInventoryScreen(event.itemStack())); + } else if (event.itemStack().getItem() == Items.WRITABLE_BOOK || event.itemStack().getItem() == Items.WRITTEN_BOOK) { + if (mc.currentScreen instanceof HandledScreen) + mc.currentScreen.close(); + mc.setScreen(new BookScreen(BookScreen.Contents.create(event.itemStack()))); + } } // Hold to preview tooltip @@ -334,7 +353,11 @@ else if (event.itemStack.getItem() == Items.FILLED_MAP && previewMaps()) { // Book preview else if ((event.itemStack.getItem() == Items.WRITABLE_BOOK || event.itemStack.getItem() == Items.WRITTEN_BOOK) && previewBooks()) { Text page = getFirstPage(event.itemStack); - if (page != null) event.tooltipData = new BookTooltipComponent(page); + if (page != null) { + int pageCount = getBookPageCount(event.itemStack); + Text pageWithCount = page.copy().append(Text.literal(String.format(" (%d pages)", pageCount)).formatted(Formatting.GRAY)); + event.tooltipData = new BookTooltipComponent(pageWithCount); + } } // Banner preview @@ -417,8 +440,9 @@ private void appendPreviewTooltipText(ItemStackTooltipEvent event, boolean space || (event.itemStack().getItem() == Items.SHIELD && banners.get()) ); - boolean showInventoryText = !openInventoryKey.get().isPressed() && ( + boolean showFullPreviewText = viewContent.get() && !viewContentKey.get().isPressed() && ( Utils.hasItems(event.itemStack()) || event.itemStack().getItem() instanceof BundleItem + || event.itemStack().getItem() == Items.WRITABLE_BOOK || event.itemStack().getItem() == Items.WRITTEN_BOOK ); if (showPreviewText) { @@ -427,9 +451,9 @@ private void appendPreviewTooltipText(ItemStackTooltipEvent event, boolean space event.appendEnd(Text.literal("Hold " + Formatting.YELLOW + keybind + Formatting.RESET + " to preview")); } - if (showInventoryText) { + if (showFullPreviewText) { if (spacer && !showPreviewText) event.appendEnd(Text.literal("")); - event.appendEnd(Text.literal("Hold " + Formatting.YELLOW + openInventoryKey.get() + Formatting.RESET + " to open inventory")); + event.appendEnd(Text.literal("Hold " + Formatting.YELLOW + viewContentKey.get() + Formatting.RESET + " to open preview")); } } @@ -462,6 +486,16 @@ private Text getFirstPage(ItemStack bookItem) { return null; } + private int getBookPageCount(ItemStack bookItem) { + if (bookItem.get(DataComponentTypes.WRITABLE_BOOK_CONTENT) != null) { + return bookItem.get(DataComponentTypes.WRITABLE_BOOK_CONTENT).pages().size(); + } else if (bookItem.get(DataComponentTypes.WRITTEN_BOOK_CONTENT) != null) { + return bookItem.get(DataComponentTypes.WRITTEN_BOOK_CONTENT).pages().size(); + } + return 0; + } + + private BannerTooltipComponent createBannerFromBannerPatternItem(ItemStack item) { // I can't imagine getting the banner pattern from a banner pattern item would fail without some serious messing around BannerPatternsComponent component = new BannerPatternsComponent.Builder().add(mc.player.getRegistryManager().getOrThrow(RegistryKeys.BANNER_PATTERN).getOrThrow(item.get(DataComponentTypes.PROVIDES_BANNER_PATTERNS)).get(0), DyeColor.WHITE).build(); From ccbba96ab7fce29bc7f46bcfaf5777844483448f Mon Sep 17 00:00:00 2001 From: noramibuu Date: Sat, 4 Oct 2025 23:07:32 +0300 Subject: [PATCH 07/13] update string to content --- .../meteorclient/systems/modules/render/BetterTooltips.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index 3ec3d58547..01aabbf329 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -453,7 +453,7 @@ private void appendPreviewTooltipText(ItemStackTooltipEvent event, boolean space if (showFullPreviewText) { if (spacer && !showPreviewText) event.appendEnd(Text.literal("")); - event.appendEnd(Text.literal("Hold " + Formatting.YELLOW + viewContentKey.get() + Formatting.RESET + " to open preview")); + event.appendEnd(Text.literal("Hold " + Formatting.YELLOW + viewContentKey.get() + Formatting.RESET + " to view contents")); } } From 8a15026981d55b60f98b20cb437cbf56a0744e5f Mon Sep 17 00:00:00 2001 From: noramibuu <50046813+noramibu@users.noreply.github.com> Date: Thu, 9 Oct 2025 20:52:25 +0300 Subject: [PATCH 08/13] remove view-content and add key option to middle-click-open --- .../gui/screens/ContainerInventoryScreen.java | 2 +- .../mixin/HandledScreenMixin.java | 26 +++---- .../modules/render/BetterTooltips.java | 72 +++++++++---------- .../meteorclient/utils/render/PeekScreen.java | 20 +++--- 4 files changed, 59 insertions(+), 61 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java index c51dc98f06..7835d39ceb 100644 --- a/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java +++ b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java @@ -139,4 +139,4 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { } } -} +} \ No newline at end of file diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java index a668028284..62014727fa 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java @@ -9,22 +9,17 @@ import meteordevelopment.meteorclient.systems.modules.misc.InventoryTweaks; import meteordevelopment.meteorclient.systems.modules.render.BetterTooltips; import meteordevelopment.meteorclient.systems.modules.render.ItemHighlight; -import meteordevelopment.meteorclient.utils.Utils; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.ingame.BookScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider; import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.component.DataComponentTypes; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; import net.minecraft.text.Text; import org.jetbrains.annotations.Nullable; -import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -33,7 +28,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import static meteordevelopment.meteorclient.MeteorClient.mc; import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_LEFT; @Mixin(HandledScreen.class) @@ -104,14 +98,20 @@ private void onMouseDragged(double mouseX, double mouseY, int button, double del private void mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable cir) { BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); - if (button == GLFW.GLFW_MOUSE_BUTTON_MIDDLE && focusedSlot != null && !focusedSlot.getStack().isEmpty() && getScreenHandler().getCursorStack().isEmpty() && tooltips.middleClickOpen()) { - ItemStack itemStack = focusedSlot.getStack(); - if (Utils.hasItems(itemStack) || itemStack.getItem() == Items.ENDER_CHEST) { - cir.setReturnValue(Utils.openContainer(focusedSlot.getStack(), ITEMS, false)); + if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(false, button, 0) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && getScreenHandler().getCursorStack().isEmpty()) { + if (tooltips.openContent(focusedSlot.getStack())) { + cir.setReturnValue(true); } - else if (itemStack.get(DataComponentTypes.WRITTEN_BOOK_CONTENT) != null || itemStack.get(DataComponentTypes.WRITABLE_BOOK_CONTENT) != null) { - close(); - mc.setScreen(new BookScreen(BookScreen.Contents.create(itemStack))); + } + } + + // Keyboard input for middle click open + @Inject(method = "keyPressed", at = @At("HEAD"), cancellable = true) + private void keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable cir) { + BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); + + if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(true, keyCode, modifiers) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && getScreenHandler().getCursorStack().isEmpty()) { + if (tooltips.openContent(focusedSlot.getStack())) { cir.setReturnValue(true); } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index 01aabbf329..9f18c77dde 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -51,7 +51,7 @@ import java.util.function.Consumer; import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_ALT; -import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_CONTROL; +import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_MIDDLE; public class BetterTooltips extends Module { public static final Color ECHEST_COLOR = new Color(0, 50, 50); @@ -79,22 +79,6 @@ public class BetterTooltips extends Module { .build() ); - private final Setting viewContent = sgGeneral.add(new BoolSetting.Builder() - .name("view-content") - .description("Enable view content functionality.") - .defaultValue(true) - .onChanged(value -> updateTooltips = true) - .build() - ); - - private final Setting viewContentKey = sgGeneral.add(new KeybindSetting.Builder() - .name("view-content-key") - .description("Key to view contents (containers, books, etc.).") - .defaultValue(Keybind.fromKey(GLFW_KEY_LEFT_CONTROL)) - .visible(() -> viewContent.get()) - .build() - ); - private final Setting middleClickOpen = sgGeneral.add(new BoolSetting.Builder() .name("middle-click-open") .description("Opens a GUI window with the inventory of the storage block or book when you middle click the item.") @@ -102,6 +86,14 @@ public class BetterTooltips extends Module { .build() ); + private final Setting middleClickKey = sgGeneral.add(new KeybindSetting.Builder() + .name("middle-click-key") + .description("Key to open contents (containers, books, etc.) when pressed on items.") + .defaultValue(Keybind.fromButton(GLFW_MOUSE_BUTTON_MIDDLE)) + .visible(() -> middleClickOpen.get()) + .build() + ); + private final Setting pauseInCreative = sgGeneral.add(new BoolSetting.Builder() .name("pause-in-creative") .description("Pauses middle click open while the player is in creative mode.") @@ -313,17 +305,6 @@ private void appendTooltip(ItemStackTooltipEvent event) { } } - if (viewContent.get() && viewContentKey.get().isPressed()) { - if (Utils.hasItems(event.itemStack()) || event.itemStack().getItem() instanceof BundleItem) { - if (mc.currentScreen instanceof HandledScreen) - mc.currentScreen.close(); - mc.setScreen(new ContainerInventoryScreen(event.itemStack())); - } else if (event.itemStack().getItem() == Items.WRITABLE_BOOK || event.itemStack().getItem() == Items.WRITTEN_BOOK) { - if (mc.currentScreen instanceof HandledScreen) - mc.currentScreen.close(); - mc.setScreen(new BookScreen(BookScreen.Contents.create(event.itemStack()))); - } - } // Hold to preview tooltip appendPreviewTooltipText(event, true); @@ -440,21 +421,11 @@ private void appendPreviewTooltipText(ItemStackTooltipEvent event, boolean space || (event.itemStack().getItem() == Items.SHIELD && banners.get()) ); - boolean showFullPreviewText = viewContent.get() && !viewContentKey.get().isPressed() && ( - Utils.hasItems(event.itemStack()) || event.itemStack().getItem() instanceof BundleItem - || event.itemStack().getItem() == Items.WRITABLE_BOOK || event.itemStack().getItem() == Items.WRITTEN_BOOK - ); - if (showPreviewText) { // we don't want to add the spacer if the tooltip is hidden if (spacer) event.appendEnd(Text.literal("")); event.appendEnd(Text.literal("Hold " + Formatting.YELLOW + keybind + Formatting.RESET + " to preview")); } - - if (showFullPreviewText) { - if (spacer && !showPreviewText) event.appendEnd(Text.literal("")); - event.appendEnd(Text.literal("Hold " + Formatting.YELLOW + viewContentKey.get() + Formatting.RESET + " to view contents")); - } } private MutableText getStatusText(StatusEffectInstance effect) { @@ -512,6 +483,31 @@ public boolean middleClickOpen() { return (isActive() && middleClickOpen.get()) && (!pauseInCreative.get() || !mc.player.isInCreativeMode()); } + public Keybind middleClickKey() { + return middleClickKey.get(); + } + + public boolean openContent(ItemStack itemStack) { + if (!middleClickOpen() || itemStack.isEmpty()) return false; + + if (itemStack.getItem() instanceof BundleItem) { + if (mc.currentScreen instanceof HandledScreen) + mc.currentScreen.close(); + mc.setScreen(new ContainerInventoryScreen(itemStack)); + return true; + } else if (Utils.hasItems(itemStack) || itemStack.getItem() == Items.ENDER_CHEST) { + Utils.openContainer(itemStack, ITEMS, false); + return true; + } else if (itemStack.getItem() == Items.WRITABLE_BOOK || itemStack.getItem() == Items.WRITTEN_BOOK) { + if (mc.currentScreen instanceof HandledScreen) + mc.currentScreen.close(); + mc.setScreen(new BookScreen(BookScreen.Contents.create(itemStack))); + return true; + } + + return false; + } + public boolean previewShulkers() { return isActive() && isPressed() && shulkers.get(); } diff --git a/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java b/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java index 3c0a232934..e3b7efb6e4 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java @@ -11,12 +11,9 @@ import meteordevelopment.meteorclient.utils.render.color.Color; import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.ingame.BookScreen; import net.minecraft.client.gui.screen.ingame.ShulkerBoxScreen; -import net.minecraft.component.DataComponentTypes; import net.minecraft.inventory.SimpleInventory; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.screen.ShulkerBoxScreenHandler; import net.minecraft.util.Identifier; import net.minecraft.util.math.ColorHelper; @@ -39,13 +36,9 @@ public PeekScreen(ItemStack storageBlock, ItemStack[] contents) { public boolean mouseClicked(double mouseX, double mouseY, int button) { BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); - if (button == GLFW.GLFW_MOUSE_BUTTON_MIDDLE && focusedSlot != null && !focusedSlot.getStack().isEmpty() && mc.player.currentScreenHandler.getCursorStack().isEmpty() && tooltips.middleClickOpen()) { + if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(false, button, 0) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && mc.player.currentScreenHandler.getCursorStack().isEmpty()) { ItemStack itemStack = focusedSlot.getStack(); - if (Utils.hasItems(itemStack) || itemStack.getItem() == Items.ENDER_CHEST) { - return Utils.openContainer(focusedSlot.getStack(), contents, false); - } else if (itemStack.get(DataComponentTypes.WRITTEN_BOOK_CONTENT) != null || itemStack.get(DataComponentTypes.WRITABLE_BOOK_CONTENT) != null) { - close(); - mc.setScreen(new BookScreen(BookScreen.Contents.create(itemStack))); + if (tooltips.openContent(itemStack)) { return true; } } @@ -60,6 +53,15 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); + + if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(true, keyCode, modifiers) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && mc.player.currentScreenHandler.getCursorStack().isEmpty()) { + ItemStack itemStack = focusedSlot.getStack(); + if (tooltips.openContent(itemStack)) { + return true; + } + } + if (keyCode == GLFW.GLFW_KEY_ESCAPE || mc.options.inventoryKey.matchesKey(keyCode, scanCode)) { close(); return true; From 0a951815f8e916d2c895d0bd947a8d7adf002908 Mon Sep 17 00:00:00 2001 From: Wide_Cat Date: Sat, 11 Oct 2025 23:57:24 +0100 Subject: [PATCH 09/13] massive fixes and improvements --- .../gui/screens/ContainerInventoryScreen.java | 29 ++++---- .../meteorclient/mixin/BundleItemMixin.java | 29 ++++++++ .../BundleTooltipSubmenuHandlerMixin.java | 31 ++++++++ .../mixin/HandledScreenMixin.java | 4 +- .../meteorclient/mixin/ItemMixin.java | 3 +- .../meteorclient/mixin/ItemStackMixin.java | 18 ----- .../systems/modules/misc/InventoryTweaks.java | 11 +++ .../modules/render/BetterTooltips.java | 20 +++--- .../meteorclient/utils/Utils.java | 2 +- .../meteorclient/utils/render/PeekScreen.java | 9 ++- .../utils/tooltip/BundleTooltipComponent.java | 71 ++++++++++++++----- src/main/resources/meteor-client.mixins.json | 2 + 12 files changed, 158 insertions(+), 71 deletions(-) create mode 100644 src/main/java/meteordevelopment/meteorclient/mixin/BundleItemMixin.java create mode 100644 src/main/java/meteordevelopment/meteorclient/mixin/BundleTooltipSubmenuHandlerMixin.java diff --git a/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java index 7835d39ceb..2a428bc9bc 100644 --- a/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java +++ b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java @@ -6,9 +6,9 @@ package meteordevelopment.meteorclient.gui.screens; import meteordevelopment.meteorclient.utils.Utils; +import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gl.RenderPipelines; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.BundleContentsComponent; import net.minecraft.entity.player.PlayerInventory; @@ -19,11 +19,11 @@ import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import static meteordevelopment.meteorclient.MeteorClient.mc; - import java.util.ArrayList; import java.util.List; +import static meteordevelopment.meteorclient.MeteorClient.mc; + /* * i couldn't figure out how to add proper outer borders for the GUI without adding custom textures. @TODO */ @@ -31,7 +31,7 @@ public class ContainerInventoryScreen extends Screen { private static final Identifier SLOT_TEXTURE = Identifier.ofVanilla("container/slot"); private static final int SLOT_SIZE = 18; private static final int SCREEN_WIDTH = 176; - + private final List containerItems; private final PlayerInventory playerInventory; private final int containerRows; @@ -42,7 +42,7 @@ public ContainerInventoryScreen(ItemStack containerItem) { super(containerItem.getName()); this.playerInventory = mc.player.getInventory(); this.tooltipContext = Item.TooltipContext.create(mc.world); - + this.containerItems = new ArrayList<>(); if (containerItem.getItem() instanceof BundleItem) { BundleContentsComponent bundleContents = containerItem.get(DataComponentTypes.BUNDLE_CONTENTS); @@ -58,7 +58,7 @@ public ContainerInventoryScreen(ItemStack containerItem) { } } } - + this.containerRows = Math.max(1, (containerItems.size() + 8) / 9); } @@ -72,18 +72,18 @@ protected void init() { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); - + int baseX = x + 8; int baseY = y + 18; int playerY = baseY + containerRows * SLOT_SIZE + 20; - + for (int row = 0; row < containerRows + 4; row++) { for (int col = 0; col < 9; col++) { int slotY = row < containerRows ? baseY + row * SLOT_SIZE : playerY + (row - containerRows) * SLOT_SIZE; context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, SLOT_TEXTURE, baseX + col * SLOT_SIZE, slotY, SLOT_SIZE, SLOT_SIZE); } } - + for (int i = 0; i < containerItems.size(); i++) { ItemStack item = containerItems.get(i); if (!item.isEmpty()) { @@ -93,7 +93,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { context.drawStackOverlay(textRenderer, item, itemX, itemY); } } - + for (int row = 0; row < 4; row++) { for (int col = 0; col < 9; col++) { int slotIndex = row < 3 ? 9 + row * 9 + col : col; @@ -106,7 +106,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { } } } - + context.getMatrices().pushMatrix(); context.getMatrices().translate((float)x, (float)y); if (textRenderer != null) { @@ -114,10 +114,10 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { context.drawText(textRenderer, playerInventory.getDisplayName(), 8, 18 + containerRows * SLOT_SIZE + 10, -12566464, false); } context.getMatrices().popMatrix(); - + if (mouseX >= baseX && mouseX < baseX + 9 * SLOT_SIZE) { int col = (mouseX - baseX) / SLOT_SIZE; - + if (mouseY >= baseY && mouseY < baseY + containerRows * SLOT_SIZE) { int index = ((mouseY - baseY) / SLOT_SIZE) * 9 + col; if (index < containerItems.size()) { @@ -138,5 +138,4 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { } } } - -} \ No newline at end of file +} diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/BundleItemMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/BundleItemMixin.java new file mode 100644 index 0000000000..15fa22b4f2 --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/mixin/BundleItemMixin.java @@ -0,0 +1,29 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.mixin; + +import meteordevelopment.meteorclient.MeteorClient; +import meteordevelopment.meteorclient.events.render.TooltipDataEvent; +import net.minecraft.item.BundleItem; +import net.minecraft.item.ItemStack; +import net.minecraft.item.tooltip.TooltipData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Optional; + +@Mixin(BundleItem.class) +public class BundleItemMixin { + @Inject(method = "getTooltipData", at = @At("HEAD"), cancellable = true) + private void onTooltipData(ItemStack stack, CallbackInfoReturnable> cir) { + TooltipDataEvent event = MeteorClient.EVENT_BUS.post(TooltipDataEvent.get(stack)); + if (event.tooltipData != null) { + cir.setReturnValue(Optional.of(event.tooltipData)); + } + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/BundleTooltipSubmenuHandlerMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/BundleTooltipSubmenuHandlerMixin.java new file mode 100644 index 0000000000..8c3a7183f6 --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/mixin/BundleTooltipSubmenuHandlerMixin.java @@ -0,0 +1,31 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.systems.modules.misc.InventoryTweaks; +import net.minecraft.client.gui.tooltip.BundleTooltipSubmenuHandler; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.BundleContentsComponent; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(BundleTooltipSubmenuHandler.class) +public class BundleTooltipSubmenuHandlerMixin { + @ModifyExpressionValue(method = "sendPacket", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/BundleItem;getNumberOfStacksShown(Lnet/minecraft/item/ItemStack;)I")) + private int uncapBundleScrolling1(int original, ItemStack item, int slotId, int selectedItemIndex) { + if (Modules.get().get(InventoryTweaks.class).uncapBundleScrolling()) return item.getOrDefault(DataComponentTypes.BUNDLE_CONTENTS, BundleContentsComponent.DEFAULT).size(); + return original; + } + + @ModifyExpressionValue(method = "onScroll", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/BundleItem;getNumberOfStacksShown(Lnet/minecraft/item/ItemStack;)I")) + private int uncapBundleScrolling2(int original, double horizontal, double vertical, int slotId, ItemStack item) { + if (Modules.get().get(InventoryTweaks.class).uncapBundleScrolling()) return item.getOrDefault(DataComponentTypes.BUNDLE_CONTENTS, BundleContentsComponent.DEFAULT).size(); + return original; + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java index 62014727fa..ca992e58b6 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java @@ -99,7 +99,7 @@ private void mouseClicked(double mouseX, double mouseY, int button, CallbackInfo BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(false, button, 0) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && getScreenHandler().getCursorStack().isEmpty()) { - if (tooltips.openContent(focusedSlot.getStack())) { + if (tooltips.openContent(focusedSlot.getStack(), ITEMS)) { cir.setReturnValue(true); } } @@ -111,7 +111,7 @@ private void keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoRe BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(true, keyCode, modifiers) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && getScreenHandler().getCursorStack().isEmpty()) { - if (tooltips.openContent(focusedSlot.getStack())) { + if (tooltips.openContent(focusedSlot.getStack(), ITEMS)) { cir.setReturnValue(true); } } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ItemMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ItemMixin.java index cfd2422820..058adad1e4 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ItemMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ItemMixin.java @@ -7,7 +7,6 @@ import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.events.render.TooltipDataEvent; - import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.tooltip.TooltipData; @@ -20,7 +19,7 @@ @Mixin(Item.class) public abstract class ItemMixin { - @Inject(method = "getTooltipData", at=@At("HEAD"), cancellable = true) + @Inject(method = "getTooltipData", at = @At("HEAD"), cancellable = true) private void onTooltipData(ItemStack stack, CallbackInfoReturnable> cir) { TooltipDataEvent event = MeteorClient.EVENT_BUS.post(TooltipDataEvent.get(stack)); if (event.tooltipData != null) { diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ItemStackMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ItemStackMixin.java index 4a63914480..21b7729b39 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ItemStackMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ItemStackMixin.java @@ -10,12 +10,9 @@ import meteordevelopment.meteorclient.events.entity.player.FinishUsingItemEvent; import meteordevelopment.meteorclient.events.entity.player.StoppedUsingItemEvent; import meteordevelopment.meteorclient.events.game.ItemStackTooltipEvent; -import meteordevelopment.meteorclient.events.render.TooltipDataEvent; import meteordevelopment.meteorclient.utils.Utils; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.item.tooltip.TooltipData; import net.minecraft.text.Text; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; @@ -25,7 +22,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; -import java.util.Optional; import static meteordevelopment.meteorclient.MeteorClient.mc; @@ -41,20 +37,6 @@ private List onGetTooltip(List original) { return original; } - @ModifyReturnValue(method = "getTooltipData", at = @At("RETURN")) - private Optional onGetTooltipData(Optional original) { - ItemStack stack = (ItemStack) (Object) this; - - if (stack.getItem() instanceof net.minecraft.item.BundleItem) { - TooltipDataEvent event = MeteorClient.EVENT_BUS.post(TooltipDataEvent.get(stack)); - if (event.tooltipData != null) { - return Optional.of(event.tooltipData); - } - } - - return original; - } - @Inject(method = "finishUsing", at = @At("HEAD")) private void onFinishUsing(World world, LivingEntity user, CallbackInfoReturnable info) { if (user == mc.player) { diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/InventoryTweaks.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/InventoryTweaks.java index d9b4106e49..7721709e74 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/InventoryTweaks.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/InventoryTweaks.java @@ -104,6 +104,13 @@ public class InventoryTweaks extends Module { .build() ); + private final Setting uncapBundleScrolling = sgGeneral.add(new BoolSetting.Builder() + .name("uncap-bundle-scrolling") + .description("Whether to uncap the bundle scrolling feature to let you select any item.") + .defaultValue(true) + .build() + ); + // Anti drop private final Setting> antiDropItems = sgAntiDrop.add(new ItemListSetting.Builder() @@ -452,6 +459,10 @@ public boolean mouseDragItemMove() { return isActive() && mouseDragItemMove.get(); } + public boolean uncapBundleScrolling() { + return isActive() && uncapBundleScrolling.get(); + } + public boolean canSteal(ScreenHandler handler) { try { return (stealScreens.get().contains(handler.getType())); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index 9f18c77dde..7917ff0b19 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -23,7 +23,6 @@ import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.tooltip.*; import meteordevelopment.orbit.EventHandler; - import net.minecraft.client.gui.screen.ingame.BookScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.component.DataComponentTypes; @@ -90,7 +89,7 @@ public class BetterTooltips extends Module { .name("middle-click-key") .description("Key to open contents (containers, books, etc.) when pressed on items.") .defaultValue(Keybind.fromButton(GLFW_MOUSE_BUTTON_MIDDLE)) - .visible(() -> middleClickOpen.get()) + .visible(middleClickOpen::get) .build() ); @@ -269,7 +268,7 @@ private void appendTooltip(ItemStackTooltipEvent event) { if (foodInfo.get() && event.itemStack().contains(DataComponentTypes.FOOD)) { FoodComponent food = event.itemStack().get(DataComponentTypes.FOOD); // Those emojis really look like in-game hunger bar - event.appendStart(Text.literal(String.format("🍖 %d hunger (💛 %.1f saturation)", food.nutrition(), food.saturation())).formatted(Formatting.GRAY)); + event.appendStart(Text.literal(String.format("🍖 %d (💛 %.1f)", food.nutrition(), food.saturation())).formatted(Formatting.GRAY)); } // Item size tooltip @@ -305,7 +304,6 @@ private void appendTooltip(ItemStackTooltipEvent event) { } } - // Hold to preview tooltip appendPreviewTooltipText(event, true); } @@ -380,7 +378,7 @@ else if (event.itemStack.getItem() instanceof BundleItem && previewBundles()) { for (ItemStack stack : bundleContents.iterate()) { bundleItems[index++] = stack; } - event.tooltipData = new BundleTooltipComponent(bundleItems, bundleContents, new Color(139, 69, 19, 255)); + event.tooltipData = new BundleTooltipComponent(bundleItems, bundleContents); } } } @@ -487,20 +485,18 @@ public Keybind middleClickKey() { return middleClickKey.get(); } - public boolean openContent(ItemStack itemStack) { + public boolean openContent(ItemStack itemStack, ItemStack[] contents) { if (!middleClickOpen() || itemStack.isEmpty()) return false; if (itemStack.getItem() instanceof BundleItem) { - if (mc.currentScreen instanceof HandledScreen) - mc.currentScreen.close(); + if (mc.currentScreen instanceof HandledScreen) mc.currentScreen.close(); mc.setScreen(new ContainerInventoryScreen(itemStack)); return true; } else if (Utils.hasItems(itemStack) || itemStack.getItem() == Items.ENDER_CHEST) { - Utils.openContainer(itemStack, ITEMS, false); + Utils.openContainer(itemStack, contents, false); return true; } else if (itemStack.getItem() == Items.WRITABLE_BOOK || itemStack.getItem() == Items.WRITTEN_BOOK) { - if (mc.currentScreen instanceof HandledScreen) - mc.currentScreen.close(); + if (mc.currentScreen instanceof HandledScreen) mc.currentScreen.close(); mc.setScreen(new BookScreen(BookScreen.Contents.create(itemStack))); return true; } @@ -536,7 +532,7 @@ private boolean previewEntities() { return isPressed() && entitiesInBuckets.get(); } - private boolean previewBundles() { + public boolean previewBundles() { return isPressed() && bundles.get(); } diff --git a/src/main/java/meteordevelopment/meteorclient/utils/Utils.java b/src/main/java/meteordevelopment/meteorclient/utils/Utils.java index a5a0ebffbe..a316bd8b2a 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/Utils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/Utils.java @@ -283,7 +283,7 @@ else if (components.contains(DataComponentTypes.BLOCK_ENTITY_DATA)) { if (slot.get() >= 0 && slot.get() < items.length) { switch (StackWithSlot.CODEC.parse(mc.player.getRegistryManager().getOps(NbtOps.INSTANCE), compound.get())) { case DataResult.Success success -> items[slot.get()] = success.value().stack(); - case DataResult.Error error -> items[slot.get()] = ItemStack.EMPTY; + case DataResult.Error ignored -> items[slot.get()] = ItemStack.EMPTY; default -> throw new MatchException(null, null); } } diff --git a/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java b/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java index e3b7efb6e4..5eebbe9fc1 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java @@ -38,9 +38,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(false, button, 0) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && mc.player.currentScreenHandler.getCursorStack().isEmpty()) { ItemStack itemStack = focusedSlot.getStack(); - if (tooltips.openContent(itemStack)) { - return true; - } + return tooltips.openContent(itemStack, contents); } return false; @@ -57,7 +55,7 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(true, keyCode, modifiers) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && mc.player.currentScreenHandler.getCursorStack().isEmpty()) { ItemStack itemStack = focusedSlot.getStack(); - if (tooltips.openContent(itemStack)) { + if (tooltips.openContent(itemStack, contents)) { return true; } } @@ -66,6 +64,7 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { close(); return true; } + return false; } @@ -84,6 +83,6 @@ protected void drawBackground(DrawContext context, float delta, int mouseX, int int i = (width - backgroundWidth) / 2; int j = (height - backgroundHeight) / 2; - context.drawTexture(RenderPipelines.GUI_TEXTURED, TEXTURE, i, j, 0f, 0f, backgroundWidth, backgroundHeight, backgroundWidth, backgroundHeight, 256, 256, ColorHelper.fromFloats(color.r / 255f, color.g / 255f, color.b / 255f, color.a / 255f)); + context.drawTexture(RenderPipelines.GUI_TEXTURED, TEXTURE, i, j, 0f, 0f, backgroundWidth, backgroundHeight, backgroundWidth, backgroundHeight, 256, 256, ColorHelper.fromFloats(color.a / 255f, color.r / 255f, color.g / 255f, color.b / 255f)); } } diff --git a/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java b/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java index 41f5e3b30e..902566e0e0 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java @@ -5,11 +5,12 @@ package meteordevelopment.meteorclient.utils.tooltip; -import meteordevelopment.meteorclient.utils.render.color.Color; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.tooltip.HoveredTooltipPositioner; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.BundleContentsComponent; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; @@ -18,28 +19,32 @@ import net.minecraft.util.math.MathHelper; import org.apache.commons.lang3.math.Fraction; +import java.util.List; + public class BundleTooltipComponent implements TooltipComponent, MeteorTooltipData { private static final Identifier BUNDLE_SLOT_BACKGROUND_TEXTURE = Identifier.ofVanilla("container/bundle/slot_background"); private static final Identifier BUNDLE_PROGRESS_BAR_BORDER_TEXTURE = Identifier.ofVanilla("container/bundle/bundle_progressbar_border"); private static final Identifier BUNDLE_PROGRESS_BAR_FILL_TEXTURE = Identifier.ofVanilla("container/bundle/bundle_progressbar_fill"); private static final Identifier BUNDLE_PROGRESS_BAR_FULL_TEXTURE = Identifier.ofVanilla("container/bundle/bundle_progressbar_full"); - + private static final Identifier BUNDLE_SLOT_HIGHLIGHT_BACK_TEXTURE = Identifier.ofVanilla("container/bundle/slot_highlight_back"); + private static final Identifier BUNDLE_SLOT_HIGHLIGHT_FRONT_TEXTURE = Identifier.ofVanilla("container/bundle/slot_highlight_front"); + private static final int SLOTS_PER_ROW = 8; private static final int SLOT_DIMENSION = 24; private static final int ROW_WIDTH = 8 + SLOTS_PER_ROW * SLOT_DIMENSION + 8; private static final int PROGRESS_BAR_WIDTH = 94; private static final int PROGRESS_BAR_HEIGHT = 13; private static final Text BUNDLE_FULL = Text.translatable("item.minecraft.bundle.full"); - + private final ItemStack[] items; private final BundleContentsComponent bundleContents; private final int width; private final int height; - public BundleTooltipComponent(ItemStack[] items, BundleContentsComponent bundleContents, Color color) { + public BundleTooltipComponent(ItemStack[] items, BundleContentsComponent bundleContents) { this.items = items; this.bundleContents = bundleContents; - + int rows = (items.length + SLOTS_PER_ROW - 1) / SLOTS_PER_ROW; this.width = ROW_WIDTH; this.height = 8 + rows * SLOT_DIMENSION + 8 + PROGRESS_BAR_HEIGHT + 4; @@ -60,6 +65,11 @@ public int getWidth(TextRenderer textRenderer) { return width; } + @Override + public boolean isSticky() { + return true; + } + @Override public void drawItems(TextRenderer textRenderer, int x, int y, int width, int height, DrawContext context) { int row = 0; @@ -69,10 +79,9 @@ public void drawItems(TextRenderer textRenderer, int x, int y, int width, int he if (!itemStack.isEmpty()) { int slotX = x + 8 + col * SLOT_DIMENSION; int slotY = y + 8 + row * SLOT_DIMENSION; - + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, BUNDLE_SLOT_BACKGROUND_TEXTURE, slotX, slotY, SLOT_DIMENSION, SLOT_DIMENSION); - - context.drawItem(itemStack, slotX + 4, slotY + 4, 0); + drawItem(itemStack, (row * 8) + col, slotX, slotY, textRenderer, context); context.drawStackOverlay(textRenderer, itemStack, slotX + 4, slotY + 4); } @@ -82,28 +91,58 @@ public void drawItems(TextRenderer textRenderer, int x, int y, int width, int he row++; } } - + + drawSelectedItemTooltip(textRenderer, context, x, y, width); + int progressBarX = x + (this.width - PROGRESS_BAR_WIDTH) / 2; int progressBarY = y + this.height - PROGRESS_BAR_HEIGHT - 4; drawProgressBar(progressBarX, progressBarY, textRenderer, context); } - + + private void drawItem(ItemStack itemStack, int index, int x, int y, TextRenderer textRenderer, DrawContext drawContext) { + boolean bl = bundleContents.getSelectedStackIndex() == index; + if (bl) { + drawContext.drawGuiTexture(RenderPipelines.GUI_TEXTURED, BUNDLE_SLOT_HIGHLIGHT_BACK_TEXTURE, x, y, 24, 24); + } else { + drawContext.drawGuiTexture(RenderPipelines.GUI_TEXTURED, BUNDLE_SLOT_BACKGROUND_TEXTURE, x, y, 24, 24); + } + + drawContext.drawItem(itemStack, x + 4, y + 4, 0); + drawContext.drawStackOverlay(textRenderer, itemStack, x + 4, y + 4); + if (bl) { + drawContext.drawGuiTexture(RenderPipelines.GUI_TEXTURED, BUNDLE_SLOT_HIGHLIGHT_FRONT_TEXTURE, x, y, 24, 24); + } + } + + private void drawSelectedItemTooltip(TextRenderer textRenderer, DrawContext drawContext, int x, int y, int width) { + if (this.bundleContents.hasSelectedStack()) { + ItemStack itemStack = this.bundleContents.get(this.bundleContents.getSelectedStackIndex()); + Text text = itemStack.getFormattedName(); + int i = textRenderer.getWidth(text.asOrderedText()); + int j = x + width / 2 - 12; + TooltipComponent tooltipComponent = TooltipComponent.of(text.asOrderedText()); + drawContext.drawTooltipImmediately( + textRenderer, List.of(tooltipComponent), j - i / 2, y - 37, HoveredTooltipPositioner.INSTANCE, itemStack.get(DataComponentTypes.TOOLTIP_STYLE) + ); + } + } + private void drawProgressBar(int x, int y, TextRenderer textRenderer, DrawContext context) { int fillAmount = MathHelper.clamp(MathHelper.multiplyFraction(bundleContents.getOccupancy(), PROGRESS_BAR_WIDTH), 0, PROGRESS_BAR_WIDTH); - - Identifier fillTexture = bundleContents.getOccupancy().compareTo(Fraction.ONE) >= 0 - ? BUNDLE_PROGRESS_BAR_FULL_TEXTURE + + Identifier fillTexture = bundleContents.getOccupancy().compareTo(Fraction.ONE) >= 0 + ? BUNDLE_PROGRESS_BAR_FULL_TEXTURE : BUNDLE_PROGRESS_BAR_FILL_TEXTURE; - + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, fillTexture, x + 1, y, fillAmount, PROGRESS_BAR_HEIGHT); context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, BUNDLE_PROGRESS_BAR_BORDER_TEXTURE, x, y, PROGRESS_BAR_WIDTH, PROGRESS_BAR_HEIGHT); - + Text label = getProgressBarLabel(); if (label != null) { context.drawCenteredTextWithShadow(textRenderer, label, x + PROGRESS_BAR_WIDTH / 2, y + 3, Colors.WHITE); } } - + private Text getProgressBarLabel() { return bundleContents.getOccupancy().compareTo(Fraction.ONE) >= 0 ? BUNDLE_FULL : null; } diff --git a/src/main/resources/meteor-client.mixins.json b/src/main/resources/meteor-client.mixins.json index 44aea0cd37..4d473d7af2 100644 --- a/src/main/resources/meteor-client.mixins.json +++ b/src/main/resources/meteor-client.mixins.json @@ -36,6 +36,8 @@ "BoxMixin", "BrewingStandScreenMixin", "BrightnessGetterMixin", + "BundleItemMixin", + "BundleTooltipSubmenuHandlerMixin", "CameraMixin", "CapabilityTrackerMixin", "CapeFeatureRendererMixin", From dbdb3f26a66c1d3b1bc4ba23e71a8c8f7a9bb064 Mon Sep 17 00:00:00 2001 From: Wide_Cat Date: Sun, 12 Oct 2025 00:21:12 +0100 Subject: [PATCH 10/13] fix sticky --- .../meteorclient/mixin/HandledScreenMixin.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java index ca992e58b6..3728634904 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java @@ -5,6 +5,7 @@ package meteordevelopment.meteorclient.mixin; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.systems.modules.misc.InventoryTweaks; import meteordevelopment.meteorclient.systems.modules.render.BetterTooltips; @@ -13,6 +14,7 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider; +import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenHandler; @@ -123,4 +125,13 @@ private void onDrawSlot(DrawContext context, Slot slot, CallbackInfo ci) { int color = Modules.get().get(ItemHighlight.class).getColor(slot.getStack()); if (color != -1) context.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, color); } + + @ModifyReturnValue(method = "isItemTooltipSticky", at = @At("RETURN")) + private boolean isTooltipSticky(boolean original, ItemStack item) { + if (item.getTooltipData().orElse(null) instanceof TooltipComponent component) { + return component.isSticky(); + } + + return original; + } } From dd29ab3b9a447188bfaef079c6b585537e932249 Mon Sep 17 00:00:00 2001 From: Wide_Cat Date: Sun, 12 Oct 2025 01:02:47 +0100 Subject: [PATCH 11/13] small ContainerInventoryScreen cleanup, a bit more to do --- .../gui/screens/ContainerInventoryScreen.java | 49 ++++++++++++++----- .../meteorclient/utils/render/PeekScreen.java | 1 + 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java index 2a428bc9bc..5cc2950691 100644 --- a/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java +++ b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java @@ -13,13 +13,14 @@ import net.minecraft.component.type.BundleContentsComponent; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.BundleItem; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static meteordevelopment.meteorclient.MeteorClient.mc; @@ -35,13 +36,11 @@ public class ContainerInventoryScreen extends Screen { private final List containerItems; private final PlayerInventory playerInventory; private final int containerRows; - private final Item.TooltipContext tooltipContext; private int x, y; public ContainerInventoryScreen(ItemStack containerItem) { super(containerItem.getName()); this.playerInventory = mc.player.getInventory(); - this.tooltipContext = Item.TooltipContext.create(mc.world); this.containerItems = new ArrayList<>(); if (containerItem.getItem() instanceof BundleItem) { @@ -52,14 +51,10 @@ public ContainerInventoryScreen(ItemStack containerItem) { } else { ItemStack[] tempItems = new ItemStack[64]; Utils.getItemsInContainerItem(containerItem, tempItems); - for (ItemStack stack : tempItems) { - if (stack != null && !stack.isEmpty()) { - containerItems.add(stack); - } - } + Collections.addAll(containerItems, tempItems); } - this.containerRows = Math.max(1, (containerItems.size() + 8) / 9); + this.containerRows = Math.max(1, MathHelper.ceilDiv(containerItems.size(), 9)); } @Override @@ -77,6 +72,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { int baseY = y + 18; int playerY = baseY + containerRows * SLOT_SIZE + 20; + // drawing the slot textures for (int row = 0; row < containerRows + 4; row++) { for (int col = 0; col < 9; col++) { int slotY = row < containerRows ? baseY + row * SLOT_SIZE : playerY + (row - containerRows) * SLOT_SIZE; @@ -84,6 +80,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { } } + // drawing the container items for (int i = 0; i < containerItems.size(); i++) { ItemStack item = containerItems.get(i); if (!item.isEmpty()) { @@ -94,6 +91,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { } } + // drawing your inventory items for (int row = 0; row < 4; row++) { for (int col = 0; col < 9; col++) { int slotIndex = row < 3 ? 9 + row * 9 + col : col; @@ -107,6 +105,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { } } + // drawing title headers context.getMatrices().pushMatrix(); context.getMatrices().translate((float)x, (float)y); if (textRenderer != null) { @@ -118,24 +117,48 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { if (mouseX >= baseX && mouseX < baseX + 9 * SLOT_SIZE) { int col = (mouseX - baseX) / SLOT_SIZE; + // tooltips for the container items if (mouseY >= baseY && mouseY < baseY + containerRows * SLOT_SIZE) { int index = ((mouseY - baseY) / SLOT_SIZE) * 9 + col; if (index < containerItems.size()) { ItemStack item = containerItems.get(index); if (!item.isEmpty()) { - context.drawTooltip(textRenderer, item.getTooltip(tooltipContext, mc.player, TooltipType.BASIC), item.getTooltipData(), mouseX, mouseY); + context.drawTooltip(textRenderer, getTooltipFromItem(mc, item), item.getTooltipData(), mouseX, mouseY); } } - } else if (mouseY >= playerY && mouseY < playerY + 4 * SLOT_SIZE) { + } + + // tooltips for your inventory items + else if (mouseY >= playerY && mouseY < playerY + 4 * SLOT_SIZE) { int row = (mouseY - playerY) / SLOT_SIZE; int slotIndex = row < 3 ? 9 + row * 9 + col : col; if (slotIndex < playerInventory.size()) { ItemStack item = playerInventory.getStack(slotIndex); if (!item.isEmpty()) { - context.drawTooltip(textRenderer, item.getTooltip(tooltipContext, mc.player, TooltipType.BASIC), item.getTooltipData(), mouseX, mouseY); + context.drawTooltip(textRenderer, getTooltipFromItem(mc, item), item.getTooltipData(), mouseX, mouseY); } } } } } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (keyCode == GLFW.GLFW_KEY_ESCAPE || mc.options.inventoryKey.matchesKey(keyCode, scanCode)) { + close(); + return true; + } + + return false; + } + + @Override + public boolean keyReleased(int keyCode, int scanCode, int modifiers) { + if (keyCode == GLFW.GLFW_KEY_ESCAPE) { + close(); + return true; + } + + return false; + } } diff --git a/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java b/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java index 5eebbe9fc1..92624cda6a 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java @@ -74,6 +74,7 @@ public boolean keyReleased(int keyCode, int scanCode, int modifiers) { close(); return true; } + return false; } From 36e390a1bc0234a7d76c767f80c795d969dc0fb8 Mon Sep 17 00:00:00 2001 From: Wide_Cat Date: Sun, 12 Oct 2025 13:31:30 +0100 Subject: [PATCH 12/13] more ContainerInventoryScreen improvements, middle click open refactors --- .../gui/screens/ContainerInventoryScreen.java | 84 +++++++++++-------- .../mixin/HandledScreenMixin.java | 12 +-- .../modules/render/BetterTooltips.java | 35 ++++---- .../meteorclient/utils/render/PeekScreen.java | 20 +---- .../utils/tooltip/BundleTooltipComponent.java | 2 +- 5 files changed, 75 insertions(+), 78 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java index 5cc2950691..ebcf6b271c 100644 --- a/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java +++ b/src/main/java/meteordevelopment/meteorclient/gui/screens/ContainerInventoryScreen.java @@ -5,6 +5,8 @@ package meteordevelopment.meteorclient.gui.screens; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.systems.modules.render.BetterTooltips; import meteordevelopment.meteorclient.utils.Utils; import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; @@ -14,7 +16,6 @@ import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.BundleItem; import net.minecraft.item.ItemStack; -import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; import org.lwjgl.glfw.GLFW; @@ -38,6 +39,9 @@ public class ContainerInventoryScreen extends Screen { private final int containerRows; private int x, y; + private int baseX, baseY; + private int playerY; + public ContainerInventoryScreen(ItemStack containerItem) { super(containerItem.getName()); this.playerInventory = mc.player.getInventory(); @@ -68,9 +72,9 @@ protected void init() { public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); - int baseX = x + 8; - int baseY = y + 18; - int playerY = baseY + containerRows * SLOT_SIZE + 20; + baseX = x + 8; + baseY = y + 18; + playerY = baseY + containerRows * SLOT_SIZE + 20; // drawing the slot textures for (int row = 0; row < containerRows + 4; row++) { @@ -107,43 +111,41 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { // drawing title headers context.getMatrices().pushMatrix(); - context.getMatrices().translate((float)x, (float)y); + context.getMatrices().translate((float) x, (float) y); if (textRenderer != null) { - context.drawText(textRenderer, title != null && !title.getString().isEmpty() ? title : Text.literal("Container"), 8, 6, -12566464, false); + context.drawText(textRenderer, title, 8, 6, -12566464, false); context.drawText(textRenderer, playerInventory.getDisplayName(), 8, 18 + containerRows * SLOT_SIZE + 10, -12566464, false); } context.getMatrices().popMatrix(); - if (mouseX >= baseX && mouseX < baseX + 9 * SLOT_SIZE) { - int col = (mouseX - baseX) / SLOT_SIZE; - - // tooltips for the container items - if (mouseY >= baseY && mouseY < baseY + containerRows * SLOT_SIZE) { - int index = ((mouseY - baseY) / SLOT_SIZE) * 9 + col; - if (index < containerItems.size()) { - ItemStack item = containerItems.get(index); - if (!item.isEmpty()) { - context.drawTooltip(textRenderer, getTooltipFromItem(mc, item), item.getTooltipData(), mouseX, mouseY); - } - } - } + // drawing the tooltip + ItemStack item = getSelectedItem(mouseX, mouseY); + if (!item.isEmpty()) { + context.drawTooltip(textRenderer, getTooltipFromItem(mc, item), item.getTooltipData(), mouseX, mouseY); + } + } - // tooltips for your inventory items - else if (mouseY >= playerY && mouseY < playerY + 4 * SLOT_SIZE) { - int row = (mouseY - playerY) / SLOT_SIZE; - int slotIndex = row < 3 ? 9 + row * 9 + col : col; - if (slotIndex < playerInventory.size()) { - ItemStack item = playerInventory.getStack(slotIndex); - if (!item.isEmpty()) { - context.drawTooltip(textRenderer, getTooltipFromItem(mc, item), item.getTooltipData(), mouseX, mouseY); - } - } - } + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); + + ItemStack stack = getSelectedItem((int) mouseX, (int) mouseY); + if (tooltips.shouldOpenContents(false, button, 0)) { + return tooltips.openContent(stack); } + + return false; } @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); + + ItemStack stack = getSelectedItem((int) mc.mouse.getScaledX(mc.getWindow()), (int) mc.mouse.getScaledY(mc.getWindow())); + if (tooltips.shouldOpenContents(true, keyCode, modifiers)) { + return tooltips.openContent(stack); + } + if (keyCode == GLFW.GLFW_KEY_ESCAPE || mc.options.inventoryKey.matchesKey(keyCode, scanCode)) { close(); return true; @@ -152,13 +154,23 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { return false; } - @Override - public boolean keyReleased(int keyCode, int scanCode, int modifiers) { - if (keyCode == GLFW.GLFW_KEY_ESCAPE) { - close(); - return true; + private ItemStack getSelectedItem(int mouseX, int mouseY) { + if (mouseX < baseX || mouseX > baseX + 9 * SLOT_SIZE) return ItemStack.EMPTY; + + int col = (mouseX - baseX) / SLOT_SIZE; + if (col > 8) return ItemStack.EMPTY; + + if (mouseY >= baseY && mouseY < baseY + containerRows * SLOT_SIZE) { + int index = ((mouseY - baseY) / SLOT_SIZE) * 9 + col; + return (index < containerItems.size() ? containerItems.get(index) : ItemStack.EMPTY); } - return false; + if (mouseY >= playerY && mouseY < playerY + 4 * SLOT_SIZE) { + int row = (mouseY - playerY) / SLOT_SIZE; + int slotIndex = row < 3 ? 9 + row * 9 + col : col; + return playerInventory.getStack(slotIndex); + } + + return ItemStack.EMPTY; } } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java index 3728634904..c451615839 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java @@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -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.callback.CallbackInfo; @@ -58,9 +57,6 @@ public abstract class HandledScreenMixin extends Screen @Shadow public abstract void close(); - @Unique - private static final ItemStack[] ITEMS = new ItemStack[27]; - public HandledScreenMixin(Text title) { super(title); } @@ -100,8 +96,8 @@ private void onMouseDragged(double mouseX, double mouseY, int button, double del private void mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable cir) { BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); - if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(false, button, 0) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && getScreenHandler().getCursorStack().isEmpty()) { - if (tooltips.openContent(focusedSlot.getStack(), ITEMS)) { + if (tooltips.shouldOpenContents(false, button, 0) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && getScreenHandler().getCursorStack().isEmpty()) { + if (tooltips.openContent(focusedSlot.getStack())) { cir.setReturnValue(true); } } @@ -112,8 +108,8 @@ private void mouseClicked(double mouseX, double mouseY, int button, CallbackInfo private void keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable cir) { BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); - if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(true, keyCode, modifiers) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && getScreenHandler().getCursorStack().isEmpty()) { - if (tooltips.openContent(focusedSlot.getStack(), ITEMS)) { + if (tooltips.shouldOpenContents(true, keyCode, modifiers) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && getScreenHandler().getCursorStack().isEmpty()) { + if (tooltips.openContent(focusedSlot.getStack())) { cir.setReturnValue(true); } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index 7917ff0b19..a36d0f3180 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -78,18 +78,18 @@ public class BetterTooltips extends Module { .build() ); - private final Setting middleClickOpen = sgGeneral.add(new BoolSetting.Builder() - .name("middle-click-open") - .description("Opens a GUI window with the inventory of the storage block or book when you middle click the item.") + private final Setting openContents = sgGeneral.add(new BoolSetting.Builder() + .name("open-contents") + .description("Opens a GUI window with the inventory of the storage block or book when you click the item.") .defaultValue(true) .build() ); - private final Setting middleClickKey = sgGeneral.add(new KeybindSetting.Builder() - .name("middle-click-key") + private final Setting openContentsKey = sgGeneral.add(new KeybindSetting.Builder() + .name("keybind") .description("Key to open contents (containers, books, etc.) when pressed on items.") .defaultValue(Keybind.fromButton(GLFW_MOUSE_BUTTON_MIDDLE)) - .visible(middleClickOpen::get) + .visible(openContents::get) .build() ); @@ -97,7 +97,7 @@ public class BetterTooltips extends Module { .name("pause-in-creative") .description("Pauses middle click open while the player is in creative mode.") .defaultValue(true) - .visible(middleClickOpen::get) + .visible(openContents::get) .build() ); @@ -227,7 +227,8 @@ public class BetterTooltips extends Module { ); private boolean updateTooltips = false; - private static final ItemStack[] ITEMS = new ItemStack[27]; + private static final ItemStack[] PREVIEW = new ItemStack[27]; + private static final ItemStack[] PEEK_SCREEN = new ItemStack[27]; public BetterTooltips() { super(Categories.Render, "better-tooltips", "Displays more useful tooltips for certain items."); @@ -312,8 +313,8 @@ private void appendTooltip(ItemStackTooltipEvent event) { private void getTooltipData(TooltipDataEvent event) { // Container preview if (previewShulkers() && Utils.hasItems(event.itemStack)) { - Utils.getItemsInContainerItem(event.itemStack, ITEMS); - event.tooltipData = new ContainerTooltipComponent(ITEMS, Utils.getShulkerColor(event.itemStack)); + Utils.getItemsInContainerItem(event.itemStack, PREVIEW); + event.tooltipData = new ContainerTooltipComponent(PREVIEW, Utils.getShulkerColor(event.itemStack)); } // EChest preview @@ -477,23 +478,23 @@ private BannerTooltipComponent createBannerFromShield(ItemStack shieldItem) { return new BannerTooltipComponent(dyeColor2, bannerPatternsComponent); } - public boolean middleClickOpen() { - return (isActive() && middleClickOpen.get()) && (!pauseInCreative.get() || !mc.player.isInCreativeMode()); + public boolean openContents() { + return (isActive() && openContents.get()) && (!pauseInCreative.get() || !mc.player.isInCreativeMode()); } - public Keybind middleClickKey() { - return middleClickKey.get(); + public boolean shouldOpenContents(boolean isKey, int keycode, int modifiers) { + return openContents() && openContentsKey.get().matches(isKey, keycode, modifiers); } - public boolean openContent(ItemStack itemStack, ItemStack[] contents) { - if (!middleClickOpen() || itemStack.isEmpty()) return false; + public boolean openContent(ItemStack itemStack) { + if (!openContents() || itemStack.isEmpty()) return false; if (itemStack.getItem() instanceof BundleItem) { if (mc.currentScreen instanceof HandledScreen) mc.currentScreen.close(); mc.setScreen(new ContainerInventoryScreen(itemStack)); return true; } else if (Utils.hasItems(itemStack) || itemStack.getItem() == Items.ENDER_CHEST) { - Utils.openContainer(itemStack, contents, false); + Utils.openContainer(itemStack, PEEK_SCREEN, false); return true; } else if (itemStack.getItem() == Items.WRITABLE_BOOK || itemStack.getItem() == Items.WRITTEN_BOOK) { if (mc.currentScreen instanceof HandledScreen) mc.currentScreen.close(); diff --git a/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java b/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java index 92624cda6a..ece9dc6f53 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/render/PeekScreen.java @@ -23,12 +23,10 @@ public class PeekScreen extends ShulkerBoxScreen { private final Identifier TEXTURE = Identifier.of("textures/gui/container/shulker_box.png"); - private final ItemStack[] contents; private final ItemStack storageBlock; public PeekScreen(ItemStack storageBlock, ItemStack[] contents) { super(new ShulkerBoxScreenHandler(0, mc.player.getInventory(), new SimpleInventory(contents)), mc.player.getInventory(), storageBlock.getName()); - this.contents = contents; this.storageBlock = storageBlock; } @@ -36,9 +34,9 @@ public PeekScreen(ItemStack storageBlock, ItemStack[] contents) { public boolean mouseClicked(double mouseX, double mouseY, int button) { BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); - if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(false, button, 0) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && mc.player.currentScreenHandler.getCursorStack().isEmpty()) { + if (tooltips.shouldOpenContents(false, button, 0) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && mc.player.currentScreenHandler.getCursorStack().isEmpty()) { ItemStack itemStack = focusedSlot.getStack(); - return tooltips.openContent(itemStack, contents); + return tooltips.openContent(itemStack); } return false; @@ -53,9 +51,9 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { public boolean keyPressed(int keyCode, int scanCode, int modifiers) { BetterTooltips tooltips = Modules.get().get(BetterTooltips.class); - if (tooltips.middleClickOpen() && tooltips.middleClickKey().matches(true, keyCode, modifiers) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && mc.player.currentScreenHandler.getCursorStack().isEmpty()) { + if (tooltips.shouldOpenContents(true, keyCode, modifiers) && focusedSlot != null && !focusedSlot.getStack().isEmpty() && mc.player.currentScreenHandler.getCursorStack().isEmpty()) { ItemStack itemStack = focusedSlot.getStack(); - if (tooltips.openContent(itemStack, contents)) { + if (tooltips.openContent(itemStack)) { return true; } } @@ -68,16 +66,6 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { return false; } - @Override - public boolean keyReleased(int keyCode, int scanCode, int modifiers) { - if (keyCode == GLFW.GLFW_KEY_ESCAPE) { - close(); - return true; - } - - return false; - } - @Override protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) { Color color = Utils.getShulkerColor(storageBlock); diff --git a/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java b/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java index 902566e0e0..be0e7c5e79 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/tooltip/BundleTooltipComponent.java @@ -144,6 +144,6 @@ private void drawProgressBar(int x, int y, TextRenderer textRenderer, DrawContex } private Text getProgressBarLabel() { - return bundleContents.getOccupancy().compareTo(Fraction.ONE) >= 0 ? BUNDLE_FULL : null; + return bundleContents.getOccupancy().compareTo(Fraction.ONE) >= 0 ? BUNDLE_FULL : Text.literal(String.format("%.2f%%", bundleContents.getOccupancy().floatValue() * 100)); } } From 820eb9103105b54fa4575b6a1691c336fd1b2aff Mon Sep 17 00:00:00 2001 From: Wide_Cat Date: Sun, 12 Oct 2025 13:37:44 +0100 Subject: [PATCH 13/13] the j --- .../meteorclient/mixin/HandledScreenMixin.java | 2 +- .../meteorclient/systems/modules/render/BetterTooltips.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java index c451615839..2d4aedabf1 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/HandledScreenMixin.java @@ -125,7 +125,7 @@ private void onDrawSlot(DrawContext context, Slot slot, CallbackInfo ci) { @ModifyReturnValue(method = "isItemTooltipSticky", at = @At("RETURN")) private boolean isTooltipSticky(boolean original, ItemStack item) { if (item.getTooltipData().orElse(null) instanceof TooltipComponent component) { - return component.isSticky(); + return original || component.isSticky(); } return original; diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java index a36d0f3180..6f7345236a 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/BetterTooltips.java @@ -465,7 +465,6 @@ private int getBookPageCount(ItemStack bookItem) { return 0; } - private BannerTooltipComponent createBannerFromBannerPatternItem(ItemStack item) { // I can't imagine getting the banner pattern from a banner pattern item would fail without some serious messing around BannerPatternsComponent component = new BannerPatternsComponent.Builder().add(mc.player.getRegistryManager().getOrThrow(RegistryKeys.BANNER_PATTERN).getOrThrow(item.get(DataComponentTypes.PROVIDES_BANNER_PATTERNS)).get(0), DyeColor.WHITE).build();