From 30b110999d871ebff0fcd19789a3e8ce5b16b84f Mon Sep 17 00:00:00 2001 From: KonaeAkira Date: Sat, 12 Feb 2022 15:29:08 +0100 Subject: Add backpack preview --- .../skyblocker/mixin/HandledScreenMixin.java | 20 ++- .../skyblocker/skyblock/BackpackPreview.java | 185 +++++++++++++++++++++ 2 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java (limited to 'src/main/java/me/xmrvizzy') diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java index d676dc25..1e3f31c4 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java @@ -1,14 +1,15 @@ package me.xmrvizzy.skyblocker.mixin; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.skyblock.BackpackPreview; import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup; -import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemListWidget; import me.xmrvizzy.skyblocker.skyblock.quicknav.QuickNav; import me.xmrvizzy.skyblocker.skyblock.quicknav.QuickNavButton; import me.xmrvizzy.skyblocker.utils.Utils; import net.minecraft.client.MinecraftClient; 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.screen.slot.Slot; import net.minecraft.text.Text; import org.jetbrains.annotations.Nullable; @@ -34,13 +35,13 @@ public abstract class HandledScreenMixin extends Screen { @Inject(method = "init()V", at = @At("TAIL")) private void init(CallbackInfo ci) { - // quicknav if (Utils.isSkyblock && SkyblockerConfig.get().general.quicknav.enableQuicknav) { String screenTitle = super.getTitle().getString().trim(); List buttons = QuickNav.init(screenTitle); for (QuickNavButton button : buttons) super.addDrawableChild(button); - } + BackpackPreview.loadStorage((HandledScreen)(Object)this); + BackpackPreview.updateStorage((HandledScreen)(Object)this); } @Inject(at = @At("HEAD"), method = "keyPressed", cancellable = true) @@ -49,4 +50,17 @@ public abstract class HandledScreenMixin extends Screen { if (WikiLookup.wikiLookup.matchesKey(keyCode, scanCode)) WikiLookup.openWiki(focusedSlot); } } + + @Inject(at = @At("HEAD"), method = "drawMouseoverTooltip", cancellable = true) + public void drawMouseOverTooltip(MatrixStack matrices, int x, int y, CallbackInfo ci) { + String title = ((HandledScreen)(Object)this).getTitle().getString(); + if (Screen.hasShiftDown() && title.equals("Storage") && focusedSlot != null) { + if (BackpackPreview.renderPreview(matrices, focusedSlot.getIndex(), x, y)) ci.cancel(); + } + } + + @Inject(method = "tick", at = @At("TAIL")) + public void tick(CallbackInfo ci) { + BackpackPreview.tick(); + } } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java new file mode 100644 index 00000000..dae5dd70 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java @@ -0,0 +1,185 @@ +package me.xmrvizzy.skyblocker.skyblock; + +import com.mojang.blaze3d.systems.RenderSystem; +import me.xmrvizzy.skyblocker.SkyblockerMod; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.*; +import net.minecraft.util.Identifier; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class BackpackPreview extends DrawableHelper { + private static final Identifier TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/inventory_background.png"); + private static final BackpackPreview instance = new BackpackPreview(); + private static final Pattern ECHEST_PATTERN = Pattern.compile("Ender Chest.*\\((\\d+)/\\d+\\)"); + private static final Pattern BACKPACK_PATTERN = Pattern.compile("Backpack.*\\((\\d+)/\\d+\\)"); + + private static final Inventory[] storage = new Inventory[27]; + private static final boolean[] dirty = new boolean[27]; + private static int counter = 0; + + private static File getSaveDir() { + String uuid = MinecraftClient.getInstance().player.getUuidAsString(); + File dir = new File("./config/skyblocker/backpack-preview/" + uuid + "/"); + dir.mkdirs(); + return dir; + } + + public static void loadStorage(HandledScreen screen) { + String title = screen.getTitle().getString(); + if (title.equals("Storage")) + for (int index = 0; index < storage.length; ++index) { + File file = new File(getSaveDir().getPath(), index + ".nbt"); + if (file.isFile()) { + try { + NbtCompound root = NbtIo.read(file); + storage[index] = new DummyInventory(root); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + private static void saveStorage(int index) { + File file = new File(getSaveDir().getPath(), index + ".nbt"); + 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, file); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static void updateStorage(HandledScreen screen) { + String title = screen.getTitle().getString(); + int index = getStorageIndexFromTitle(title); + if (index != -1) { + storage[index] = ((HandledScreen)screen).getScreenHandler().slots.get(0).inventory; + dirty[index] = true; + } + } + + public static void tick() { + if (++counter == 200) { + counter = 0; + for (int i = 0; i < dirty.length; ++i) + if (dirty[i]) { + saveStorage(i); + dirty[i] = false; + } + } + } + + public static boolean renderPreview(MatrixStack matrices, 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; + + Screen screen = MinecraftClient.getInstance().currentScreen; + int x = mouseX + 184 >= screen.width ? mouseX - 188 : mouseX + 8; + int y = Math.max(0, mouseY - 16); + + RenderSystem.disableDepthTest(); + RenderSystem.setShaderTexture(0, TEXTURE); + instance.drawTexture(matrices, x, y, 0, 0, 176, 7); + for (int i = 0; i < rows; ++i) + instance.drawTexture(matrices, x, y + i * 18 + 7, 0, 7, 176, 18); + instance.drawTexture(matrices, x, y + rows * 18 + 7, 0, 25, 176, 7); + RenderSystem.enableDepthTest(); + + ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer(); + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + for (int i = 9; i < storage[index].size(); ++i) { + int itemX = x + (i - 9) % 9 * 18 + 8; + int itemY = y + (i - 9) / 9 * 18 + 8; + itemRenderer.zOffset = 200.0F; + itemRenderer.renderInGui(storage[index].getStack(i), itemX, itemY); + itemRenderer.renderGuiItemOverlay(textRenderer, storage[index].getStack(i), itemX, itemY); + itemRenderer.zOffset = 0.0F; + } + + return true; + } + + private static int getStorageIndexFromTitle(String title) { + Matcher echest = ECHEST_PATTERN.matcher(title); + if (echest.find()) return Integer.parseInt(echest.group(1)) - 1; + Matcher backpack = BACKPACK_PATTERN.matcher(title); + if (backpack.find()) return Integer.parseInt(backpack.group(1)) + 8; + return -1; + } +} + +class DummyInventory implements Inventory { + private List 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); } + + @Override + public ItemStack removeStack(int slot, int amount) { return null; } + + @Override + public ItemStack removeStack(int slot) { return null; } + + @Override + public void setStack(int slot, ItemStack stack) { stacks.set(slot, stack); } + + @Override + public void markDirty() {} + + @Override + public boolean canPlayerUse(PlayerEntity player) { return false; } + + @Override + public void clear() {} +} \ No newline at end of file -- cgit From dc00f0e6ad5dd20eda599d2aa6c544c3b19b380a Mon Sep 17 00:00:00 2001 From: KonaeAkira Date: Sat, 12 Feb 2022 15:44:23 +0100 Subject: Fix bug where the backpack preview wouldn't update in some cases Also moved the tick() call to a more reasonable location --- src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java | 2 ++ src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java | 5 ----- src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java | 6 ++++-- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src/main/java/me/xmrvizzy') diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java index db702e81..575a87d3 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java +++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java @@ -3,6 +3,7 @@ package me.xmrvizzy.skyblocker; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import me.xmrvizzy.skyblocker.container.ContainerSolverManager; import me.xmrvizzy.skyblocker.discord.DiscordRPCManager; +import me.xmrvizzy.skyblocker.skyblock.BackpackPreview; import me.xmrvizzy.skyblocker.skyblock.dungeon.DungeonBlaze; import me.xmrvizzy.skyblocker.utils.Utils; import net.minecraft.client.MinecraftClient; @@ -30,6 +31,7 @@ public class SkyblockerMod { if (client == null) return; ticks++; if(onHypxiel()) { + BackpackPreview.tick(); if (ticks % 4 == 0) try { if (Utils.isDungeons) { diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java index 1e3f31c4..88676f08 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/HandledScreenMixin.java @@ -58,9 +58,4 @@ public abstract class HandledScreenMixin extends Screen { if (BackpackPreview.renderPreview(matrices, focusedSlot.getIndex(), x, y)) ci.cancel(); } } - - @Inject(method = "tick", at = @At("TAIL")) - public void tick(CallbackInfo ci) { - BackpackPreview.tick(); - } } diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java index dae5dd70..4bf474e4 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java @@ -92,12 +92,14 @@ public class BackpackPreview extends DrawableHelper { } public static void tick() { - if (++counter == 200) { + if (++counter == 100) { counter = 0; for (int i = 0; i < dirty.length; ++i) if (dirty[i]) { saveStorage(i); - dirty[i] = false; + String title = MinecraftClient.getInstance().currentScreen.getTitle().getString(); + int index = getStorageIndexFromTitle(title); + dirty[i] = i == index; } } } -- cgit From d8d5caef17b72d59b0f65c1ebf5860b00d5082f0 Mon Sep 17 00:00:00 2001 From: KonaeAkira Date: Sat, 12 Feb 2022 16:00:48 +0100 Subject: Only load storage content from disk once What was I thinking :) --- .../skyblocker/skyblock/BackpackPreview.java | 25 +++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'src/main/java/me/xmrvizzy') diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java index 4bf474e4..6942968c 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java @@ -29,6 +29,7 @@ public class BackpackPreview extends DrawableHelper { private static final Inventory[] storage = new Inventory[27]; private static final boolean[] dirty = new boolean[27]; + private static boolean loaded = false; private static int counter = 0; private static File getSaveDir() { @@ -39,19 +40,23 @@ public class BackpackPreview extends DrawableHelper { } public static void loadStorage(HandledScreen screen) { - String title = screen.getTitle().getString(); - if (title.equals("Storage")) - for (int index = 0; index < storage.length; ++index) { - File file = new File(getSaveDir().getPath(), index + ".nbt"); - if (file.isFile()) { - try { - NbtCompound root = NbtIo.read(file); - storage[index] = new DummyInventory(root); - } catch (Exception e) { - e.printStackTrace(); + if (!loaded) { + String title = screen.getTitle().getString(); + if (title.equals("Storage")) { + for (int index = 0; index < storage.length; ++index) { + File file = new File(getSaveDir().getPath(), index + ".nbt"); + if (file.isFile()) { + try { + NbtCompound root = NbtIo.read(file); + storage[index] = new DummyInventory(root); + } catch (Exception e) { + e.printStackTrace(); + } } } + loaded = true; } + } } private static void saveStorage(int index) { -- cgit From d47cc0cd93f74b02d3eb5ec5f622ba0450290829 Mon Sep 17 00:00:00 2001 From: KonaeAkira Date: Thu, 24 Feb 2022 12:00:30 +0100 Subject: Use the new scheduler and use fabricLoader to get config dir --- .../java/me/xmrvizzy/skyblocker/SkyblockerMod.java | 1 + .../skyblocker/skyblock/BackpackPreview.java | 35 +++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src/main/java/me/xmrvizzy') diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java index 2c0a8ad6..f3c851f1 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java +++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java @@ -19,6 +19,7 @@ public class SkyblockerMod { scheduler.scheduleCyclic(Utils::sbChecker, 20); scheduler.scheduleCyclic(discordRPCManager::update, 100); scheduler.scheduleCyclic(DungeonBlaze::update, 4); + scheduler.scheduleCyclic(BackpackPreview::tick, 100); } public static SkyblockerMod getInstance() { diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java index 6942968c..13aa9944 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/BackpackPreview.java @@ -2,6 +2,8 @@ package me.xmrvizzy.skyblocker.skyblock; import com.mojang.blaze3d.systems.RenderSystem; import me.xmrvizzy.skyblocker.SkyblockerMod; +import me.xmrvizzy.skyblocker.utils.Utils; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawableHelper; @@ -26,15 +28,25 @@ public class BackpackPreview extends DrawableHelper { private static final BackpackPreview instance = new BackpackPreview(); private static final Pattern ECHEST_PATTERN = Pattern.compile("Ender Chest.*\\((\\d+)/\\d+\\)"); private static final Pattern BACKPACK_PATTERN = Pattern.compile("Backpack.*\\((\\d+)/\\d+\\)"); + private static final int STORAGE_SIZE = 27; - private static final Inventory[] storage = new Inventory[27]; - private static final boolean[] dirty = new boolean[27]; + private static final Inventory[] storage = new Inventory[STORAGE_SIZE]; + private static final boolean[] dirty = new boolean[STORAGE_SIZE]; private static boolean loaded = false; - private static int counter = 0; + + public static void tick() { + if (Utils.isOnSkyblock) { + for (int index = 0; index < STORAGE_SIZE; ++index) + if (dirty[index]) saveStorage(index); + String title = MinecraftClient.getInstance().currentScreen.getTitle().getString(); + int index = getStorageIndexFromTitle(title); + if (index != -1) dirty[index] = true; + } + } private static File getSaveDir() { String uuid = MinecraftClient.getInstance().player.getUuidAsString(); - File dir = new File("./config/skyblocker/backpack-preview/" + uuid + "/"); + File dir = FabricLoader.getInstance().getConfigDir().resolve("skyblocker/backpack-preview/" + uuid).toFile(); dir.mkdirs(); return dir; } @@ -43,7 +55,7 @@ public class BackpackPreview extends DrawableHelper { if (!loaded) { String title = screen.getTitle().getString(); if (title.equals("Storage")) { - for (int index = 0; index < storage.length; ++index) { + for (int index = 0; index < STORAGE_SIZE; ++index) { File file = new File(getSaveDir().getPath(), index + ".nbt"); if (file.isFile()) { try { @@ -96,19 +108,6 @@ public class BackpackPreview extends DrawableHelper { } } - public static void tick() { - if (++counter == 100) { - counter = 0; - for (int i = 0; i < dirty.length; ++i) - if (dirty[i]) { - saveStorage(i); - String title = MinecraftClient.getInstance().currentScreen.getTitle().getString(); - int index = getStorageIndexFromTitle(title); - dirty[i] = i == index; - } - } - } - public static boolean renderPreview(MatrixStack matrices, int index, int mouseX, int mouseY) { if (index >= 9 && index < 18) index -= 9; else if (index >= 27 && index < 45) index -= 18; -- cgit