Skip to content

Commit

Permalink
Merge pull request #302 from viciscat/compactor_preview
Browse files Browse the repository at this point in the history
Personal Compactor/Deletor preview
  • Loading branch information
kevinthegreat1 authored Sep 16, 2023
2 parents 1130273 + 3881303 commit 045e5c5
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public ItemData(String itemName) {
public static class General {
public boolean acceptReparty = true;
public boolean backpackPreviewWithoutShift = false;
public boolean compactorDeletorPreview = true;
public boolean hideEmptyTooltips = true;
public boolean hideStatusEffectOverlay = false;

Expand Down
32 changes: 21 additions & 11 deletions src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import me.xmrvizzy.skyblocker.SkyblockerMod;
import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
import me.xmrvizzy.skyblocker.skyblock.BackpackPreview;
import me.xmrvizzy.skyblocker.skyblock.dungeon.DungeonChestProfit;
import me.xmrvizzy.skyblocker.skyblock.experiment.ChronomatronSolver;
import me.xmrvizzy.skyblocker.skyblock.experiment.ExperimentSolver;
import me.xmrvizzy.skyblocker.skyblock.experiment.SuperpairsSolver;
import me.xmrvizzy.skyblocker.skyblock.experiment.UltrasequencerSolver;
import me.xmrvizzy.skyblocker.skyblock.item.BackpackPreview;
import me.xmrvizzy.skyblocker.skyblock.item.CompactorDeletorPreview;
import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup;
import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry;
import me.xmrvizzy.skyblocker.utils.Utils;
import me.xmrvizzy.skyblocker.utils.render.gui.ContainerSolver;
import net.minecraft.client.gui.DrawContext;
Expand All @@ -17,13 +18,10 @@
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.text.Text;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
Expand All @@ -34,10 +32,8 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;

import java.util.Map;
import java.util.regex.Matcher;

@Mixin(HandledScreen.class)
public abstract class HandledScreenMixin extends Screen {
Expand All @@ -56,18 +52,31 @@ protected HandledScreenMixin(Text title) {
}
}

@Inject(at = @At("HEAD"), method = "drawMouseoverTooltip", cancellable = true)
@SuppressWarnings("DataFlowIssue")
// makes intellij be quiet about this.focusedSlot maybe being null. It's already null checked in mixined method.
@Inject(method = "drawMouseoverTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTooltip(Lnet/minecraft/client/font/TextRenderer;Ljava/util/List;Ljava/util/Optional;II)V"), cancellable = true)
public void skyblocker$drawMouseOverTooltip(DrawContext context, int x, int y, CallbackInfo ci) {
if (!Utils.isOnSkyblock()) return;

// Hide Empty Tooltips
if (Utils.isOnSkyblock() && SkyblockerConfig.get().general.hideEmptyTooltips && this.focusedSlot != null && focusedSlot.getStack().getName().getString().equals(" ")) {
if (SkyblockerConfig.get().general.hideEmptyTooltips && focusedSlot.getStack().getName().getString().equals(" ")) {
ci.cancel();
}

// Backpack Preview
boolean shiftDown = SkyblockerConfig.get().general.backpackPreviewWithoutShift ^ Screen.hasShiftDown();
if (this.client != null && this.client.player != null && this.focusedSlot != null && shiftDown && this.getTitle().getString().equals("Storage") && this.focusedSlot.inventory != this.client.player.getInventory() && BackpackPreview.renderPreview(context, this.focusedSlot.getIndex(), x, y)) {
if (shiftDown && getTitle().getString().equals("Storage") && focusedSlot.inventory != client.player.getInventory() && BackpackPreview.renderPreview(context, focusedSlot.getIndex(), x, y)) {
ci.cancel();
}

// Compactor Preview
if (SkyblockerConfig.get().general.compactorDeletorPreview) {
ItemStack stack = focusedSlot.getStack();
Matcher matcher = CompactorDeletorPreview.NAME.matcher(ItemRegistry.getInternalName(stack));
if (matcher.matches() && CompactorDeletorPreview.drawPreview(context, stack, matcher.group("type"), matcher.group("size"), x, y)) {
ci.cancel();
}
}
}

@Redirect(method = "drawMouseoverTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/slot/Slot;getStack()Lnet/minecraft/item/ItemStack;", ordinal = 0))
Expand All @@ -80,6 +89,7 @@ protected HandledScreenMixin(Text title) {
return skyblocker$experimentSolvers$getStack(slot, stack);
}


@Unique
private ItemStack skyblocker$experimentSolvers$getStack(Slot slot, ItemStack stack) {
ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package me.xmrvizzy.skyblocker.mixin.accessor;

import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.tooltip.TooltipComponent;
import net.minecraft.client.gui.tooltip.TooltipPositioner;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;

import java.util.List;

@Mixin(DrawContext.class)
public interface DrawContextInvoker {

@Invoker
void invokeDrawTooltip(TextRenderer textRenderer, List<TooltipComponent> components, int x, int y, TooltipPositioner positioner);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package me.xmrvizzy.skyblocker.skyblock;
package me.xmrvizzy.skyblocker.skyblock.item;

import com.mojang.blaze3d.systems.RenderSystem;
import me.xmrvizzy.skyblocker.SkyblockerMod;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package me.xmrvizzy.skyblocker.skyblock.item;

import it.unimi.dsi.fastutil.ints.IntIntPair;
import it.unimi.dsi.fastutil.ints.IntObjectPair;
import me.xmrvizzy.skyblocker.mixin.accessor.DrawContextInvoker;
import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.tooltip.HoveredTooltipPositioner;
import net.minecraft.client.gui.tooltip.TooltipComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;

import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class CompactorDeletorPreview {
/**
* The width and height in slots of the compactor/deletor
*/
private static final Map<String, IntIntPair> DIMENSIONS = Map.of(
"4000", IntIntPair.of(1, 1),
"5000", IntIntPair.of(1, 3),
"6000", IntIntPair.of(1, 7),
"7000", IntIntPair.of(2, 6)
);
private static final IntIntPair DEFAULT_DIMENSION = IntIntPair.of(1, 6);
public static final Pattern NAME = Pattern.compile("PERSONAL_(?<type>COMPACTOR|DELETOR)_(?<size>\\d+)");
private static final MinecraftClient client = MinecraftClient.getInstance();

public static boolean drawPreview(DrawContext context, ItemStack stack, String type, String size, int x, int y) {
List<Text> tooltips = Screen.getTooltipFromItem(client, stack);
int targetIndex = getTargetIndex(tooltips);
if (targetIndex == -1) return false;

// Get items in compactor or deletor
NbtCompound nbt = stack.getNbt();
if (nbt == null || !nbt.contains("ExtraAttributes", 10)) {
return false;
}
NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes");
// Get the slots and their items from the nbt, which is in the format personal_compact_<slot_number> or personal_deletor_<slot_number>
List<IntObjectPair<ItemStack>> slots = extraAttributes.getKeys().stream().filter(slot -> slot.contains(type.toLowerCase().substring(0, 7))).map(slot -> IntObjectPair.of(Integer.parseInt(slot.substring(17)), ItemRegistry.getItemStack(extraAttributes.getString(slot)))).toList();

List<TooltipComponent> components = tooltips.stream().map(Text::asOrderedText).map(TooltipComponent::of).collect(Collectors.toList());
IntIntPair dimensions = DIMENSIONS.getOrDefault(size, DEFAULT_DIMENSION);

// If there are no items in compactor or deletor
if (slots.isEmpty()) {
int slotsCount = dimensions.leftInt() * dimensions.rightInt();
components.add(targetIndex, TooltipComponent.of(Text.literal(slotsCount + (slotsCount == 1 ? " slot" : " slots")).formatted(Formatting.GRAY).asOrderedText()));

((DrawContextInvoker) context).invokeDrawTooltip(client.textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE);
return true;
}

// Add the preview tooltip component
components.add(targetIndex, new CompactorPreviewTooltipComponent(slots, dimensions));

// Render accompanying text
components.add(targetIndex, TooltipComponent.of(Text.literal("Contents:").asOrderedText()));
if (extraAttributes.contains("PERSONAL_DELETOR_ACTIVE")) {
components.add(targetIndex, TooltipComponent.of(Text.literal("Active: ")
.append(extraAttributes.getBoolean("PERSONAL_DELETOR_ACTIVE") ? Text.literal("YES").formatted(Formatting.BOLD).formatted(Formatting.GREEN) : Text.literal("NO").formatted(Formatting.BOLD).formatted(Formatting.RED)).asOrderedText()));
}
((DrawContextInvoker) context).invokeDrawTooltip(client.textRenderer, components, x, y, HoveredTooltipPositioner.INSTANCE);
return true;
}

/**
* Finds the target index to insert the preview component, which is the second empty line
*/
private static int getTargetIndex(List<Text> tooltips) {
int targetIndex = -1;
int lineCount = 0;
for (int i = 0; i < tooltips.size(); i++) {
if (tooltips.get(i).getString().isEmpty()) {
lineCount += 1;
}
if (lineCount == 2) {
targetIndex = i;
break;
}
}
return targetIndex;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package me.xmrvizzy.skyblocker.skyblock.item;

import it.unimi.dsi.fastutil.ints.IntIntPair;
import it.unimi.dsi.fastutil.ints.IntObjectPair;
import me.xmrvizzy.skyblocker.SkyblockerMod;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.tooltip.TooltipComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;

public class CompactorPreviewTooltipComponent implements TooltipComponent {
private static final Identifier INVENTORY_TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/inventory_background.png");
private final Iterable<IntObjectPair<ItemStack>> items;
private final IntIntPair dimensions;

public CompactorPreviewTooltipComponent(Iterable<IntObjectPair<ItemStack>> items, IntIntPair dimensions) {
this.items = items;
this.dimensions = dimensions;
}

@Override
public int getHeight() {
return dimensions.leftInt() * 18 + 14;
}

@Override
public int getWidth(TextRenderer textRenderer) {
return dimensions.rightInt() * 18 + 14;
}

@Override
public void drawItems(TextRenderer textRenderer, int x, int y, DrawContext context) {
context.drawTexture(INVENTORY_TEXTURE, x, y, 0, 0, 7 + dimensions.rightInt() * 18, 7);
context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions.rightInt() * 18, y, 169, 0, 7, 7);

for (int i = 0; i < dimensions.leftInt(); i++) {
context.drawTexture(INVENTORY_TEXTURE, x, y + 7 + i * 18, 0, 7, 7, 18);
for (int j = 0; j < dimensions.rightInt(); j++) {
context.drawTexture(INVENTORY_TEXTURE, x + 7 + j * 18, y + 7 + i * 18, 7, 7, 18, 18);
}
context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions.rightInt() * 18, y + 7 + i * 18, 169, 7, 7, 18);
}
context.drawTexture(INVENTORY_TEXTURE, x, y + 7 + dimensions.leftInt() * 18, 0, 25, 7 + dimensions.rightInt() * 18, 7);
context.drawTexture(INVENTORY_TEXTURE, x + 7 + dimensions.rightInt() * 18, y + 7 + dimensions.leftInt() * 18, 169, 25, 7, 7);

for (IntObjectPair<ItemStack> entry : items) {
int itemX = x + entry.leftInt() % dimensions.rightInt() * 18 + 8;
int itemY = y + entry.leftInt() / dimensions.rightInt() * 18 + 8;
context.drawItem(entry.right(), itemX, itemY);
context.drawItemInSlot(textRenderer, entry.right(), itemX, itemY);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,9 @@ public static String getInternalName(ItemStack itemStack) {
if (itemStack.getNbt() == null) return "";
return itemStack.getNbt().getCompound("ExtraAttributes").getString("id");
}

public static ItemStack getItemStack(String internalName) {
return itemsMap.get(internalName);
}
}

1 change: 1 addition & 0 deletions src/main/resources/assets/skyblocker/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"text.autoconfig.skyblocker.option.general.quiverWarning.enableQuiverWarningInDungeons": "Enable Quiver Warning In Dungeons",
"text.autoconfig.skyblocker.option.general.quiverWarning.enableQuiverWarningAfterDungeon": "Enable Quiver Warning After a Dungeon",
"text.autoconfig.skyblocker.option.general.backpackPreviewWithoutShift": "View backpack preview without holding Shift",
"text.autoconfig.skyblocker.option.general.compactorDeletorPreview": "Enable Compactor/Deletor Preview",
"text.autoconfig.skyblocker.option.general.tabHud": "Fancy tab HUD",
"text.autoconfig.skyblocker.option.general.tabHud.tabHudEnabled": "Enable fancy tab HUD",
"text.autoconfig.skyblocker.option.general.tabHud.tabHudScale": "Scale factor of fancy tab HUD",
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/skyblocker.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"accessor.PlayerListHudAccessor",
"accessor.RecipeBookWidgetAccessor",
"accessor.ScreenAccessor",
"accessor.WorldRendererAccessor"
"accessor.WorldRendererAccessor",
"accessor.DrawContextInvoker"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit 045e5c5

Please sign in to comment.