Skip to content

Commit

Permalink
Fix BetterTooltips crashing over items with the HIDE_TOOLTIP flag (Me…
Browse files Browse the repository at this point in the history
  • Loading branch information
0xTas authored Oct 9, 2024
1 parent 37cb315 commit fa5fe9b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,55 @@

package meteordevelopment.meteorclient.events.game;

import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;

import java.util.List;

public record ItemStackTooltipEvent(ItemStack itemStack, List<Text> list) {}
public class ItemStackTooltipEvent {
private final ItemStack itemStack;
private List<Text> list;

public ItemStackTooltipEvent(ItemStack itemStack, List<Text> list) {
this.itemStack = itemStack;
this.list = list;
}

public List<Text> list() {
return list;
}

public ItemStack itemStack() {
return itemStack;
}

public void appendStart(Text text) {
copyIfImmutable();
int index = list.isEmpty() ? 0 : 1;
list.add(index, text);
}

public void appendEnd(Text text) {
copyIfImmutable();
list.add(text);
}

public void append(int index, Text text) {
copyIfImmutable();
list.add(index, text);
}

public void set(int index, Text text) {
copyIfImmutable();
list.set(index, text);
}

private void copyIfImmutable() {
// ItemStack#getTooltip can sometimes return List.of(), which is immutable.
// Some modules like BetterTooltips try to modify that list anyway, which causes a crash if we don't replace it.
if (List.of().getClass().getSuperclass().isInstance(list)) {
list = new ObjectArrayList<>(list);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,20 +253,27 @@ public BetterTooltips() {

@EventHandler
private void appendTooltip(ItemStackTooltipEvent event) {
// Hide hidden (empty) tooltips unless the tooltip hide flag setting is true.
if (!tooltip.get() && event.list().isEmpty()) {
// Hold-to-preview tooltip text is always added when needed.
appendPreviewTooltipText(event, false);
return;
}

// Status effects
if (statusEffects.get()) {
if (event.itemStack().getItem() == Items.SUSPICIOUS_STEW) {
SuspiciousStewEffectsComponent stewEffectsComponent = event.itemStack().get(DataComponentTypes.SUSPICIOUS_STEW_EFFECTS);
if (stewEffectsComponent != null) {
for (StewEffect effectTag : stewEffectsComponent.effects()) {
StatusEffectInstance effect = new StatusEffectInstance(effectTag.effect(), effectTag.duration(), 0);
event.list().add(1, getStatusText(effect));
event.appendStart(getStatusText(effect));
}
}
} else {
FoodComponent food = event.itemStack().get(DataComponentTypes.FOOD);
if (food != null) {
food.effects().forEach(e -> event.list().add(1, getStatusText(e.effect())));
food.effects().forEach(e -> event.appendStart(getStatusText(e.effect())));
}
}
}
Expand All @@ -277,12 +284,12 @@ private void appendTooltip(ItemStackTooltipEvent event) {
BlockStateComponent blockStateComponent = event.itemStack().get(DataComponentTypes.BLOCK_STATE);
if (blockStateComponent != null) {
String level = blockStateComponent.properties().get("honey_level");
event.list().add(1, Text.literal(String.format("%sHoney level: %s%s%s.", Formatting.GRAY, Formatting.YELLOW, level, Formatting.GRAY)));
event.appendStart(Text.literal(String.format("%sHoney level: %s%s%s.", Formatting.GRAY, Formatting.YELLOW, level, Formatting.GRAY)));
}

List<BeehiveBlockEntity.BeeData> bees = event.itemStack().get(DataComponentTypes.BEES);
if (bees != null) {
event.list().add(1, Text.literal(String.format("%sBees: %s%d%s.", Formatting.GRAY, Formatting.YELLOW, bees.size(), Formatting.GRAY)));
event.appendStart(Text.literal(String.format("%sBees: %s%d%s.", Formatting.GRAY, Formatting.YELLOW, bees.size(), Formatting.GRAY)));
}
}
}
Expand All @@ -300,25 +307,14 @@ private void appendTooltip(ItemStackTooltipEvent event) {
if (byteCount >= 1024) count = String.format("%.2f kb", byteCount / (float) 1024);
else count = String.format("%d bytes", byteCount);

event.list().add(Text.literal(count).formatted(Formatting.GRAY));
event.appendEnd(Text.literal(count).formatted(Formatting.GRAY));
} catch (Exception e) {
event.list().add(Text.literal("Error getting bytes.").formatted(Formatting.RED));
event.appendEnd(Text.literal("Error getting bytes.").formatted(Formatting.RED));
}
}

// Hold to preview tooltip
if ((shulkers.get() && !previewShulkers() && Utils.hasItems(event.itemStack()))
|| (event.itemStack().getItem() == Items.ENDER_CHEST && echest.get() && !previewEChest())
|| (event.itemStack().getItem() == Items.FILLED_MAP && maps.get() && !previewMaps())
|| (event.itemStack().getItem() == Items.WRITABLE_BOOK && books.get() && !previewBooks())
|| (event.itemStack().getItem() == Items.WRITTEN_BOOK && books.get() && !previewBooks())
|| (event.itemStack().getItem() instanceof EntityBucketItem && entitiesInBuckets.get() && !previewEntities())
|| (event.itemStack().getItem() instanceof BannerItem && banners.get() && !previewBanners())
|| (event.itemStack().getItem() instanceof BannerPatternItem && banners.get() && !previewBanners())
|| (event.itemStack().getItem() == Items.SHIELD && banners.get() && !previewBanners())) {
event.list().add(Text.literal(""));
event.list().add(Text.literal("Hold " + Formatting.YELLOW + keybind + Formatting.RESET + " to preview"));
}
appendPreviewTooltipText(event, true);
}

@EventHandler
Expand Down Expand Up @@ -408,6 +404,24 @@ public void applyCompactShulkerTooltip(ItemStack shulkerItem, List<Text> tooltip
}
}

private void appendPreviewTooltipText(ItemStackTooltipEvent event, boolean spacer) {
if (!isPressed() && (
shulkers.get() && Utils.hasItems(event.itemStack())
|| (event.itemStack().getItem() == Items.ENDER_CHEST && echest.get())
|| (event.itemStack().getItem() == Items.FILLED_MAP && maps.get())
|| (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 BannerItem && banners.get())
|| (event.itemStack().getItem() instanceof BannerPatternItem && banners.get())
|| (event.itemStack().getItem() == Items.SHIELD && banners.get())
)) {
// 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"));
}
}

private MutableText getStatusText(StatusEffectInstance effect) {
MutableText text = Text.translatable(effect.getTranslationKey());
if (effect.getAmplifier() != 0) {
Expand Down

0 comments on commit fa5fe9b

Please sign in to comment.