diff options
Diffstat (limited to 'src/main/java/de/hysky')
3 files changed, 129 insertions, 152 deletions
diff --git a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java index e65bc576..597faa3d 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java @@ -41,15 +41,15 @@ import java.util.regex.Matcher; @Mixin(HandledScreen.class) public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen { /** - * This is the slot id returned for when a click is outside of the screen's bounds + * This is the slot id returned for when a click is outside the screen's bounds */ @Unique private static final int OUT_OF_BOUNDS_SLOT = -999; - + @Shadow @Nullable protected Slot focusedSlot; - + @Shadow @Final protected T handler; @@ -78,7 +78,7 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen // Backpack Preview boolean shiftDown = SkyblockerConfigManager.get().general.backpackPreviewWithoutShift ^ Screen.hasShiftDown(); - if (shiftDown && getTitle().getString().equals("Storage") && focusedSlot.inventory != client.player.getInventory() && BackpackPreview.renderPreview(context, focusedSlot.getIndex(), x, y)) { + if (shiftDown && getTitle().getString().equals("Storage") && focusedSlot.inventory != client.player.getInventory() && BackpackPreview.renderPreview(context, this, focusedSlot.getIndex(), x, y)) { ci.cancel(); } @@ -133,21 +133,21 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen } } } - + /** * The naming of this method in yarn is half true, its mostly to handle slot/item interactions (which are mouse or keyboard clicks) * For example, using the drop key bind while hovering over an item will invoke this method to drop the players item */ @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true) private void skyblocker$onSlotInteract(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { - if (Utils.isOnSkyblock()) { + if (Utils.isOnSkyblock()) { // When you try and drop the item by picking it up then clicking outside of the screen if (slotId == OUT_OF_BOUNDS_SLOT) { ItemStack cursorStack = this.handler.getCursorStack(); if (ItemProtection.isItemProtected(cursorStack)) ci.cancel(); } - + if (slot != null) { // When you click your drop key while hovering over an item if (actionType == SlotActionType.THROW) { @@ -155,35 +155,36 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen if (ItemProtection.isItemProtected(stack)) ci.cancel(); } - + //Prevent salvaging if (this.getTitle().getString().equals("Salvage Items")) { ItemStack stack = slot.getStack(); if (ItemProtection.isItemProtected(stack)) ci.cancel(); } - + //Prevent selling to NPC shops if (this.client != null && this.handler instanceof GenericContainerScreenHandler genericContainerScreenHandler && genericContainerScreenHandler.getRows() == 6) { ItemStack sellItem = this.handler.slots.get(49).getStack(); - + if (sellItem.getName().getString().equals("Sell Item") || skyblocker$doesLoreContain(sellItem, this.client, "buyback")) { ItemStack stack = slot.getStack(); - + if (ItemProtection.isItemProtected(stack)) ci.cancel(); } } } - } + } } - + //TODO make this a util method somewhere else, eventually private static boolean skyblocker$doesLoreContain(ItemStack stack, MinecraftClient client, String searchString) { return stack.getTooltip(client.player, TooltipContext.BASIC).stream().map(Text::getString).anyMatch(line -> line.contains(searchString)); } - + @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V")) private void skyblocker$drawItemRarityBackground(DrawContext context, Slot slot, CallbackInfo ci) { - if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) ItemRarityBackgrounds.tryDraw(slot.getStack(), context, slot.x, slot.y); + if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) + ItemRarityBackgrounds.tryDraw(slot.getStack(), context, slot.x, slot.y); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/BackpackPreview.java b/src/main/java/de/hysky/skyblocker/skyblock/item/BackpackPreview.java index f856a255..d621d388 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/BackpackPreview.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/BackpackPreview.java @@ -1,7 +1,6 @@ package de.hysky.skyblocker.skyblock.item; import com.mojang.blaze3d.systems.RenderSystem; -import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Utils; import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; @@ -12,38 +11,43 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SimpleInventory; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.*; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtInt; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NbtList; import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; public class BackpackPreview { private static final Logger LOGGER = LoggerFactory.getLogger(BackpackPreview.class); - private static final Identifier TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/inventory_background.png"); + private static final Identifier TEXTURE = new Identifier("textures/gui/container/generic_54.png"); private static final Pattern ECHEST_PATTERN = Pattern.compile("Ender Chest.*\\((\\d+)/\\d+\\)"); private static final Pattern BACKPACK_PATTERN = Pattern.compile("Backpack.*\\(Slot #(\\d+)\\)"); private static final int STORAGE_SIZE = 27; - private static final Inventory[] storage = new Inventory[STORAGE_SIZE]; - private static final boolean[] dirty = new boolean[STORAGE_SIZE]; + private static final Storage[] storages = new Storage[STORAGE_SIZE]; - private static String loaded = ""; // uuid + sb profile currently loaded - private static Path save_dir = null; + /** + * The profile id of the currently loaded backpack preview. + */ + private static String loaded; + private static Path saveDir; public static void init() { ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { if (screen instanceof HandledScreen<?> handledScreen) { - updateStorage(handledScreen); + ScreenEvents.remove(screen).register(screen1 -> updateStorage(handledScreen)); } }); } @@ -52,98 +56,67 @@ public class BackpackPreview { Utils.update(); // force update isOnSkyblock to prevent crash on disconnect if (Utils.isOnSkyblock()) { // save all dirty storages - saveStorage(); - // update save dir based on uuid and sb profile - String uuid = MinecraftClient.getInstance().getSession().getUuidOrNull().toString().replaceAll("-", ""); - String profile = Utils.getProfile(); - if (profile != null && !profile.isEmpty()) { - save_dir = FabricLoader.getInstance().getConfigDir().resolve("skyblocker/backpack-preview/" + uuid + "/" + profile); - save_dir.toFile().mkdirs(); - if (loaded.equals(uuid + "/" + profile)) { - // mark currently opened storage as dirty - if (MinecraftClient.getInstance().currentScreen != null) { - String title = MinecraftClient.getInstance().currentScreen.getTitle().getString(); - int index = getStorageIndexFromTitle(title); - if (index != -1) dirty[index] = true; - } - } else { - // load storage again because uuid/profile changed - loaded = uuid + "/" + profile; - loadStorage(); - } + saveStorages(); + // update save dir based on sb profile id + String id = MinecraftClient.getInstance().getSession().getUuidOrNull().toString().replaceAll("-", "") + "/" + Utils.getProfileId(); + if (!id.equals(loaded)) { + saveDir = FabricLoader.getInstance().getConfigDir().resolve("skyblocker/backpack-preview/" + id); + //noinspection ResultOfMethodCallIgnored + saveDir.toFile().mkdirs(); + // load storage again because profile id changed + loaded = id; + loadStorages(); } } } - public static void loadStorage() { - assert (save_dir != null); + private static void loadStorages() { for (int index = 0; index < STORAGE_SIZE; ++index) { - storage[index] = null; - dirty[index] = false; - File file = save_dir.resolve(index + ".nbt").toFile(); - if (file.isFile()) { + storages[index] = null; + File storageFile = saveDir.resolve(index + ".nbt").toFile(); + if (storageFile.isFile()) { try { - NbtCompound root = NbtIo.read(file); - storage[index] = new DummyInventory(root); + storages[index] = Storage.fromNbt(Objects.requireNonNull(NbtIo.read(storageFile))); } catch (Exception e) { - LOGGER.error("Failed to load backpack preview file: " + file.getName(), e); + LOGGER.error("Failed to load backpack preview file: " + storageFile.getName(), e); } } } } - private static void saveStorage() { - assert (save_dir != null); + private static void saveStorages() { for (int index = 0; index < STORAGE_SIZE; ++index) { - if (dirty[index]) { - if (storage[index] != null) { - try { - NbtCompound root = new NbtCompound(); - NbtList list = new NbtList(); - for (int i = 9; i < storage[index].size(); ++i) { - ItemStack stack = storage[index].getStack(i); - NbtCompound item = new NbtCompound(); - if (stack.isEmpty()) { - item.put("id", NbtString.of("minecraft:air")); - item.put("Count", NbtInt.of(1)); - } else { - item.put("id", NbtString.of(stack.getItem().toString())); - item.put("Count", NbtInt.of(stack.getCount())); - item.put("tag", stack.getNbt()); - } - list.add(item); - } - root.put("list", list); - root.put("size", NbtInt.of(storage[index].size() - 9)); - NbtIo.write(root, save_dir.resolve(index + ".nbt").toFile()); - dirty[index] = false; - } catch (Exception e) { - LOGGER.error("Failed to save backpack preview file: " + index + ".nbt", e); - } - } + if (storages[index] != null && storages[index].dirty) { + saveStorage(index); } } } - public static void updateStorage(HandledScreen<?> screen) { - String title = screen.getTitle().getString(); + private static void saveStorage(int index) { + try { + NbtIo.write(storages[index].toNbt(), saveDir.resolve(index + ".nbt").toFile()); + storages[index].markClean(); + } catch (Exception e) { + LOGGER.error("Failed to save backpack preview file: " + index + ".nbt", e); + } + } + + private static void updateStorage(HandledScreen<?> handledScreen) { + String title = handledScreen.getTitle().getString(); int index = getStorageIndexFromTitle(title); if (index != -1) { - storage[index] = screen.getScreenHandler().slots.get(0).inventory; - dirty[index] = true; + storages[index] = new Storage(handledScreen.getScreenHandler().slots.get(0).inventory, title, true); } } - public static boolean renderPreview(DrawContext context, int index, int mouseX, int mouseY) { + public static boolean renderPreview(DrawContext context, Screen screen, int index, int mouseX, int mouseY) { if (index >= 9 && index < 18) index -= 9; else if (index >= 27 && index < 45) index -= 18; else return false; - if (storage[index] == null) return false; - int rows = (storage[index].size() - 9) / 9; + if (storages[index] == null) return false; + int rows = (storages[index].size() - 9) / 9; - Screen screen = MinecraftClient.getInstance().currentScreen; - if (screen == null) return false; int x = mouseX + 184 >= screen.width ? mouseX - 188 : mouseX + 8; int y = Math.max(0, mouseY - 16); @@ -152,27 +125,24 @@ public class BackpackPreview { matrices.translate(0f, 0f, 400f); RenderSystem.enableDepthTest(); - context.drawTexture(TEXTURE, x, y, 0, 0, 176, 7); - for (int i = 0; i < rows; ++i) { - context.drawTexture(TEXTURE, x, y + i * 18 + 7, 0, 7, 176, 18); - } - context.drawTexture(TEXTURE, x, y + rows * 18 + 7, 0, 25, 176, 7); + context.drawTexture(TEXTURE, x, y, 0, 0, 176, rows * 18 + 17); + context.drawTexture(TEXTURE, x, y + rows * 18 + 17, 0, 215, 176, 7); TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - for (int i = 9; i < storage[index].size(); ++i) { - ItemStack currentStack = storage[index].getStack(i); + context.drawText(textRenderer, storages[index].name, x + 8, y + 6, 0x404040, false); + + matrices.translate(0f, 0f, 200f); + for (int i = 9; i < storages[index].size(); ++i) { + ItemStack currentStack = storages[index].getStack(i); int itemX = x + (i - 9) % 9 * 18 + 8; - int itemY = y + (i - 9) / 9 * 18 + 8; + int itemY = y + (i - 9) / 9 * 18 + 18; if (SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) { ItemRarityBackgrounds.tryDraw(currentStack, context, itemX, itemY); } - matrices.push(); - matrices.translate(0f, 0f, 200f); context.drawItem(currentStack, itemX, itemY); context.drawItemInSlot(textRenderer, currentStack, itemX, itemY); - matrices.pop(); } matrices.pop(); @@ -187,59 +157,47 @@ public class BackpackPreview { if (backpack.find()) return Integer.parseInt(backpack.group(1)) + 8; return -1; } -} - -class DummyInventory implements Inventory { - private final List<ItemStack> stacks; - - public DummyInventory(NbtCompound root) { - stacks = new ArrayList<>(root.getInt("size") + 9); - for (int i = 0; i < 9; ++i) stacks.add(ItemStack.EMPTY); - root.getList("list", NbtCompound.COMPOUND_TYPE).forEach(item -> - stacks.add(ItemStack.fromNbt((NbtCompound) item)) - ); - } - - @Override - public int size() { - return stacks.size(); - } - - @Override - public boolean isEmpty() { - return false; - } - @Override - public ItemStack getStack(int slot) { - return stacks.get(slot); - } + static class Storage { + private final Inventory inventory; + private final String name; + private boolean dirty; - @Override - public ItemStack removeStack(int slot, int amount) { - return null; - } + private Storage(Inventory inventory, String name, boolean dirty) { + this.inventory = inventory; + this.name = name; + this.dirty = dirty; + } - @Override - public ItemStack removeStack(int slot) { - return null; - } + private int size() { + return inventory.size(); + } - @Override - public void setStack(int slot, ItemStack stack) { - stacks.set(slot, stack); - } + private ItemStack getStack(int index) { + return inventory.getStack(index); + } - @Override - public void markDirty() { - } + private void markClean() { + dirty = false; + } - @Override - public boolean canPlayerUse(PlayerEntity player) { - return false; - } + @NotNull + private static Storage fromNbt(NbtCompound root) { + SimpleInventory inventory = new SimpleInventory(root.getList("list", NbtCompound.COMPOUND_TYPE).stream().map(NbtCompound.class::cast).map(ItemStack::fromNbt).toArray(ItemStack[]::new)); + return new Storage(inventory, root.getString("name"), false); + } - @Override - public void clear() { + @NotNull + private NbtCompound toNbt() { + NbtCompound root = new NbtCompound(); + NbtList list = new NbtList(); + for (int i = 0; i < size(); ++i) { + list.add(getStack(i).writeNbt(new NbtCompound())); + } + root.put("list", list); + root.put("size", NbtInt.of(size())); + root.putString("name", name); + return root; + } } } diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java index bbfd1101..1205c71b 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Utils.java +++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java @@ -38,11 +38,19 @@ public class Utils { private static boolean isInDungeons = false; private static boolean isInjected = false; /** - * The following fields store data returned from /locraw: {@link #profile}, {@link #server}, {@link #gameType}, {@link #locationRaw}, and {@link #map}. + * The profile name parsed from the player list. */ - @SuppressWarnings("JavadocDeclaration") @NotNull private static String profile = ""; + /** + * The profile id parsed from the chat. + */ + @NotNull + private static String profileId = ""; + /** + * The following fields store data returned from /locraw: {@link #server}, {@link #gameType}, {@link #locationRaw}, and {@link #map}. + */ + @SuppressWarnings("JavadocDeclaration") @NotNull private static String server = ""; @NotNull @@ -89,6 +97,11 @@ public class Utils { return profile; } + @NotNull + public static String getProfileId() { + return profileId; + } + /** * @return the server parsed from /locraw. */ @@ -323,7 +336,7 @@ public class Utils { } /** - * Parses the /locraw reply from the server + * Parses the /locraw reply from the server and updates the player's profile id * * @return not display the message in chat is the command is sent by the mod */ @@ -349,6 +362,11 @@ public class Utils { return shouldFilter; } } + + if (isOnSkyblock && message.startsWith("Profile ID: ")) { + profileId = message.replace("Profile ID: ", ""); + } + return true; } |