aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/skyblock/item
diff options
context:
space:
mode:
authormsg-programs <msgdoesstuff@gmail.com>2023-10-31 21:03:42 +0100
committermsg-programs <msgdoesstuff@gmail.com>2023-10-31 21:03:42 +0100
commitd560c4611e603fa9e72ff6842bc14518d7bdbd63 (patch)
tree36eb1e24443bc9d9fbba51e14f12e5aacfac935c /src/main/java/de/hysky/skyblocker/skyblock/item
parent1df4ef827d8a2e2fcc3767c1f5bf961f16b7fa19 (diff)
parent5bb91104d3275283d7479f0b35c1b18be470d632 (diff)
downloadSkyblocker-d560c4611e603fa9e72ff6842bc14518d7bdbd63.tar.gz
Skyblocker-d560c4611e603fa9e72ff6842bc14518d7bdbd63.tar.bz2
Skyblocker-d560c4611e603fa9e72ff6842bc14518d7bdbd63.zip
Merge branch 'master' of https://github.com/SkyblockerMod/Skyblocker into cleanup-2
# Conflicts: # src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java # src/main/java/de/hysky/skyblocker/utils/Http.java # src/main/java/de/hysky/skyblocker/utils/render/title/TitleContainerConfigScreen.java Pull changes from upstream master
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock/item')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/BackpackPreview.java235
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java15
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java23
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/CustomItemNames.java11
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java9
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java144
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java30
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java204
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/CompactorDeletorPreview.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/item/CompactorDeletorPreview.java)6
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/CompactorPreviewTooltipComponent.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/item/CompactorPreviewTooltipComponent.java)2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ExoticTooltip.java96
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/item/PriceInfoTooltip.java)285
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java145
13 files changed, 764 insertions, 441 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/BackpackPreview.java b/src/main/java/de/hysky/skyblocker/skyblock/item/BackpackPreview.java
deleted file mode 100644
index 122ffe9b..00000000
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/BackpackPreview.java
+++ /dev/null
@@ -1,235 +0,0 @@
-package de.hysky.skyblocker.skyblock.item;
-
-import com.mojang.blaze3d.systems.RenderSystem;
-import de.hysky.skyblocker.SkyblockerMod;
-import de.hysky.skyblocker.utils.Utils;
-import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
-import net.fabricmc.loader.api.FabricLoader;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.font.TextRenderer;
-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.item.ItemStack;
-import net.minecraft.nbt.*;
-import net.minecraft.util.Identifier;
-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.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 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 String loaded = ""; // uuid + sb profile currently loaded
- private static Path save_dir = null;
-
- public static void init() {
- ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
- if (screen instanceof HandledScreen<?> handledScreen) {
- updateStorage(handledScreen);
- }
- });
- }
-
- public static void tick() {
- 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();
- }
- }
- }
- }
-
- public static void loadStorage() {
- assert (save_dir != null);
- 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()) {
- try {
- NbtCompound root = NbtIo.read(file);
- storage[index] = new DummyInventory(root);
- } catch (Exception e) {
- LOGGER.error("Failed to load backpack preview file: " + file.getName(), e);
- }
- }
- }
- }
-
- private static void saveStorage() {
- assert (save_dir != null);
- 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);
- }
- }
- }
- }
- }
-
- public static void updateStorage(HandledScreen<?> screen) {
- String title = screen.getTitle().getString();
- int index = getStorageIndexFromTitle(title);
- if (index != -1) {
- storage[index] = screen.getScreenHandler().slots.get(0).inventory;
- dirty[index] = true;
- }
- }
-
- public static boolean renderPreview(DrawContext context, 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;
- if (screen == null) return false;
- int x = mouseX + 184 >= screen.width ? mouseX - 188 : mouseX + 8;
- int y = Math.max(0, mouseY - 16);
-
- RenderSystem.disableDepthTest();
- RenderSystem.setShaderTexture(0, TEXTURE);
- 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);
- RenderSystem.enableDepthTest();
-
- MatrixStack matrices = context.getMatrices();
- 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;
- matrices.push();
- matrices.translate(0, 0, 200);
- context.drawItem(storage[index].getStack(i), itemX, itemY);
- context.drawItemInSlot(textRenderer, storage[index].getStack(i), itemX, itemY);
- matrices.pop();
- }
-
- 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 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);
- }
-
- @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() {
- }
-}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java
index 1496c90f..509f79b7 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java
@@ -4,6 +4,7 @@ import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
@@ -34,7 +35,7 @@ public class CustomArmorDyeColors {
ItemStack heldItem = source.getPlayer().getMainHandStack();
if (hex != null && !isHexadecimalColor(hex)) {
- source.sendError(Text.translatable("skyblocker.customDyeColors.invalidHex"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customDyeColors.invalidHex")));
return Command.SINGLE_SUCCESS;
}
@@ -49,24 +50,24 @@ public class CustomArmorDyeColors {
if (customDyeColors.containsKey(itemUuid)) {
customDyeColors.removeInt(itemUuid);
SkyblockerConfigManager.save();
- source.sendFeedback(Text.translatable("skyblocker.customDyeColors.removed"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.customDyeColors.removed")));
} else {
- source.sendFeedback(Text.translatable("skyblocker.customDyeColors.neverHad"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.customDyeColors.neverHad")));
}
} else {
customDyeColors.put(itemUuid, Integer.decode("0x" + hex.replace("#", "")).intValue());
SkyblockerConfigManager.save();
- source.sendFeedback(Text.translatable("skyblocker.customDyeColors.added"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.customDyeColors.added")));
}
} else {
- source.sendError(Text.translatable("skyblocker.customDyeColors.noItemUuid"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customDyeColors.noItemUuid")));
}
} else {
- source.sendError(Text.translatable("skyblocker.customDyeColors.notDyeable"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customDyeColors.notDyeable")));
return Command.SINGLE_SUCCESS;
}
} else {
- source.sendError(Text.translatable("skyblocker.customDyeColors.unableToSetColor"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customDyeColors.unableToSetColor")));
}
return Command.SINGLE_SUCCESS;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java
index 9242d47b..cec84b38 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java
@@ -3,8 +3,12 @@ package de.hysky.skyblocker.skyblock.item;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.suggestion.SuggestionProvider;
+import com.mojang.serialization.Codec;
+import com.mojang.serialization.codecs.RecordCodecBuilder;
+
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.events.SkyblockEvents;
+import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
import dev.isxander.yacl3.config.v2.api.SerialEntry;
@@ -105,38 +109,43 @@ public class CustomArmorTrims {
if (customArmorTrims.containsKey(itemUuid)) {
customArmorTrims.remove(itemUuid);
SkyblockerConfigManager.save();
- source.sendFeedback(Text.translatable("skyblocker.customArmorTrims.removed"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.customArmorTrims.removed")));
} else {
- source.sendFeedback(Text.translatable("skyblocker.customArmorTrims.neverHad"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.customArmorTrims.neverHad")));
}
} else {
// Ensure that the material & trim are valid
ArmorTrimId trimId = new ArmorTrimId(material, pattern);
if (TRIMS_CACHE.get(trimId) == null) {
- source.sendError(Text.translatable("skyblocker.customArmorTrims.invalidMaterialOrPattern"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customArmorTrims.invalidMaterialOrPattern")));
return Command.SINGLE_SUCCESS;
}
customArmorTrims.put(itemUuid, trimId);
SkyblockerConfigManager.save();
- source.sendFeedback(Text.translatable("skyblocker.customArmorTrims.added"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.customArmorTrims.added")));
}
} else {
- source.sendError(Text.translatable("skyblocker.customArmorTrims.noItemUuid"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customArmorTrims.noItemUuid")));
}
} else {
- source.sendError(Text.translatable("skyblocker.customArmorTrims.notAnArmorPiece"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customArmorTrims.notAnArmorPiece")));
return Command.SINGLE_SUCCESS;
}
} else {
- source.sendError(Text.translatable("skyblocker.customArmorTrims.unableToSetTrim"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customArmorTrims.unableToSetTrim")));
}
return Command.SINGLE_SUCCESS;
}
public record ArmorTrimId(@SerialEntry Identifier material, @SerialEntry Identifier pattern) implements Pair<Identifier, Identifier> {
+ public static final Codec<ArmorTrimId> CODEC = RecordCodecBuilder.create(instance -> instance.group(
+ Identifier.CODEC.fieldOf("material").forGetter(ArmorTrimId::material),
+ Identifier.CODEC.fieldOf("pattern").forGetter(ArmorTrimId::pattern))
+ .apply(instance, ArmorTrimId::new));
+
@Override
public Identifier left() {
return material();
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomItemNames.java b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomItemNames.java
index b6213eb6..e47444cf 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomItemNames.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomItemNames.java
@@ -3,6 +3,7 @@ package de.hysky.skyblocker.skyblock.item;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
@@ -42,9 +43,9 @@ public class CustomItemNames {
//Remove custom item name when the text argument isn't passed
customItemNames.remove(itemUuid);
SkyblockerConfigManager.save();
- source.sendFeedback(Text.translatable("skyblocker.customItemNames.removed"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.customItemNames.removed")));
} else {
- source.sendFeedback(Text.translatable("skyblocker.customItemNames.neverHad"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.customItemNames.neverHad")));
}
} else {
//If the text is provided then set the item's custom name to it
@@ -55,13 +56,13 @@ public class CustomItemNames {
customItemNames.put(itemUuid, text);
SkyblockerConfigManager.save();
- source.sendFeedback(Text.translatable("skyblocker.customItemNames.added"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.customItemNames.added")));
}
} else {
- source.sendError(Text.translatable("skyblocker.customItemNames.noItemUuid"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customItemNames.noItemUuid")));
}
} else {
- source.sendError(Text.translatable("skyblocker.customItemNames.unableToSetName"));
+ source.sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.customItemNames.unableToSetName")));
}
return Command.SINGLE_SUCCESS;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java
index ff88ef8d..2d929c28 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java
@@ -3,6 +3,7 @@ package de.hysky.skyblocker.skyblock.item;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
@@ -44,18 +45,18 @@ public class ItemProtection {
protectedItems.add(itemUuid);
SkyblockerConfigManager.save();
- source.sendFeedback(Text.translatable("skyblocker.itemProtection.added", heldItem.getName()));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.itemProtection.added", heldItem.getName())));
} else {
protectedItems.remove(itemUuid);
SkyblockerConfigManager.save();
- source.sendFeedback(Text.translatable("skyblocker.itemProtection.removed", heldItem.getName()));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.itemProtection.removed", heldItem.getName())));
}
} else {
- source.sendFeedback(Text.translatable("skyblocker.itemProtection.noItemUuid"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.itemProtection.noItemUuid")));
}
} else {
- source.sendFeedback(Text.translatable("skyblocker.itemProtection.unableToProtect"));
+ source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.itemProtection.unableToProtect")));
}
return Command.SINGLE_SUCCESS;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java b/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java
new file mode 100644
index 00000000..ac9b1bf0
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java
@@ -0,0 +1,144 @@
+package de.hysky.skyblocker.skyblock.item;
+
+import java.io.ByteArrayInputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.util.Base64;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.reflect.TypeToken;
+import com.mojang.util.UndashedUuid;
+
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.utils.Http;
+import de.hysky.skyblocker.utils.Http.ApiResponse;
+import de.hysky.skyblocker.utils.Utils;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.nbt.NbtCompound;
+import net.minecraft.nbt.NbtElement;
+import net.minecraft.nbt.NbtIo;
+import net.minecraft.nbt.NbtList;
+import net.minecraft.util.Util;
+
+public class MuseumItemCache {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MuseumItemCache.class);
+ private static final Path CACHE_FILE = SkyblockerMod.CONFIG_DIR.resolve("museum_item_cache.json");
+ private static final Object2ObjectOpenHashMap<String, Object2ObjectOpenHashMap<String, ProfileMuseumData>> MUSEUM_ITEM_CACHE = new Object2ObjectOpenHashMap<>();
+ private static final Type MAP_TYPE = new TypeToken<Object2ObjectOpenHashMap<String, Object2ObjectOpenHashMap<String, ProfileMuseumData>>>() {}.getType();
+
+ private static CompletableFuture<Void> loaded;
+
+ public static void init() {
+ ClientLifecycleEvents.CLIENT_STARTED.register(MuseumItemCache::load);
+ }
+
+ private static void load(MinecraftClient client) {
+ loaded = CompletableFuture.runAsync(() -> {
+ try (BufferedReader reader = Files.newBufferedReader(CACHE_FILE)) {
+ Object2ObjectOpenHashMap<String, Object2ObjectOpenHashMap<String, ProfileMuseumData>> cachedData = SkyblockerMod.GSON.fromJson(reader, MAP_TYPE);
+
+ MUSEUM_ITEM_CACHE.putAll(cachedData);
+ LOGGER.info("[Skyblocker] Loaded museum items cache");
+ } catch (NoSuchFileException ignored) {
+ } catch (IOException e) {
+ LOGGER.error("[Skyblocker] Failed to load cached museum items", e);
+ }
+ });
+ }
+
+ private static void save() {
+ CompletableFuture.runAsync(() -> {
+ try (BufferedWriter writer = Files.newBufferedWriter(CACHE_FILE)) {
+ SkyblockerMod.GSON.toJson(MUSEUM_ITEM_CACHE, writer);
+ } catch (IOException e) {
+ LOGGER.error("[Skyblocker] Failed to save cached museum items!", e);
+ }
+ });
+ }
+
+ private static void updateData4ProfileMember(String uuid, String profileId) {
+ CompletableFuture.runAsync(() -> {
+ try (ApiResponse response = Http.sendHypixelRequest("skyblock/museum", "?profile=" + profileId)) {
+ //The request was successful
+ if (response.ok()) {
+ JsonObject profileData = JsonParser.parseString(response.content()).getAsJsonObject();
+ JsonObject memberData = profileData.get("members").getAsJsonObject().get(uuid).getAsJsonObject();
+
+ //We call them sets because it could either be a singular item or an entire armour set
+ Map<String, JsonElement> donatedSets = memberData.get("items").getAsJsonObject().asMap();
+
+ //Set of all found item ids on profile
+ ObjectOpenHashSet<String> itemIds = new ObjectOpenHashSet<>();
+
+ for (Map.Entry<String, JsonElement> donatedSet : donatedSets.entrySet()) {
+ //Item is plural here because the nbt is a list
+ String itemsData = donatedSet.getValue().getAsJsonObject().get("items").getAsJsonObject().get("data").getAsString();
+ NbtList items = NbtIo.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(itemsData))).getList("i", NbtElement.COMPOUND_TYPE);
+
+ for (int i = 0; i < items.size(); i++) {
+ NbtCompound tag = items.getCompound(i).getCompound("tag");
+
+ if (tag.contains("ExtraAttributes")) {
+ NbtCompound extraAttributes = tag.getCompound("ExtraAttributes");
+
+ if (extraAttributes.contains("id")) itemIds.add(extraAttributes.getString("id"));
+ }
+ }
+ }
+
+ MUSEUM_ITEM_CACHE.get(uuid).put(profileId, new ProfileMuseumData(System.currentTimeMillis(), itemIds));
+ save();
+
+ LOGGER.info("[Skyblocker] Successfully updated museum item cache for profile {}", profileId);
+ }
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker] Failed to refresh museum item data for profile {}", profileId, e);
+ }
+ });
+ }
+
+ /**
+ * The cache is ticked upon switching skyblock servers
+ */
+ public static void tick(String profileId) {
+ if (loaded.isDone()) {
+ String uuid = UndashedUuid.toString(MinecraftClient.getInstance().getSession().getUuidOrNull());
+ Object2ObjectOpenHashMap<String, ProfileMuseumData> playerData = MUSEUM_ITEM_CACHE.computeIfAbsent(uuid, uuid1 -> Util.make(new Object2ObjectOpenHashMap<>(), map -> {
+ map.put(profileId, ProfileMuseumData.EMPTY);
+ }));
+
+ if (playerData.get(profileId).stale()) updateData4ProfileMember(uuid, profileId);
+ }
+ }
+
+ public static boolean hasItemInMuseum(String id) {
+ String uuid = UndashedUuid.toString(MinecraftClient.getInstance().getSession().getUuidOrNull());
+ ObjectOpenHashSet<String> collectedItemIds = MUSEUM_ITEM_CACHE.get(uuid).get(Utils.getProfileId()).collectedItemIds();
+
+ return collectedItemIds != null && collectedItemIds.contains(id);
+ }
+
+ private record ProfileMuseumData(long lastUpdated, ObjectOpenHashSet<String> collectedItemIds) {
+ private static final ProfileMuseumData EMPTY = new ProfileMuseumData(0L, null);
+ private static final long MAX_AGE = 86_400_000;
+
+ private boolean stale() {
+ return System.currentTimeMillis() > lastUpdated + MAX_AGE;
+ }
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java b/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java
index d4e6a0df..38121ea3 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java
@@ -1,23 +1,25 @@
package de.hysky.skyblocker.skyblock.item;
-import de.hysky.skyblocker.skyblock.itemlist.ItemRegistry;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.itemlist.ItemRepository;
import de.hysky.skyblocker.utils.ItemUtils;
-import de.hysky.skyblocker.utils.Utils;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
-import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
+import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import org.lwjgl.glfw.GLFW;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.concurrent.CompletableFuture;
public class WikiLookup {
+ private static final Logger LOGGER = LoggerFactory.getLogger(WikiLookup.class);
public static KeyBinding wikiLookup;
- static final MinecraftClient client = MinecraftClient.getInstance();
- static String id;
+ private static String id;
public static void init() {
wikiLookup = KeyBindingHelper.registerKeyBinding(new KeyBinding(
@@ -28,22 +30,22 @@ public class WikiLookup {
));
}
- public static String getSkyblockId(Slot slot) {
+ public static void getSkyblockId(Slot slot) {
//Grabbing the skyblock NBT data
ItemUtils.getItemIdOptional(slot.getStack()).ifPresent(newId -> id = newId);
- return id;
}
- public static void openWiki(Slot slot) {
- if (Utils.isOnSkyblock()) {
- id = getSkyblockId(slot);
+ public static void openWiki(Slot slot, PlayerEntity player) {
+ if (SkyblockerConfigManager.get().general.wikiLookup.enableWikiLookup) {
+ getSkyblockId(slot);
try {
- String wikiLink = ItemRegistry.getWikiLink(id);
+ String wikiLink = ItemRepository.getWikiLink(id, player);
CompletableFuture.runAsync(() -> Util.getOperatingSystem().open(wikiLink));
} catch (IndexOutOfBoundsException | IllegalStateException e) {
- e.printStackTrace();
- if (client.player != null)
- client.player.sendMessage(Text.of("Error while retrieving wiki article..."), false);
+ LOGGER.error("[Skyblocker] Error while retrieving wiki article...", e);
+ if (player != null) {
+ player.sendMessage(Text.of("[Skyblocker] Error while retrieving wiki article, see logs..."), false);
+ }
}
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java
new file mode 100644
index 00000000..5627b56d
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java
@@ -0,0 +1,204 @@
+package de.hysky.skyblocker.skyblock.item.tooltip;
+
+import com.mojang.blaze3d.systems.RenderSystem;
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds;
+import de.hysky.skyblocker.utils.Utils;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.font.TextRenderer;
+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.inventory.Inventory;
+import net.minecraft.inventory.SimpleInventory;
+import net.minecraft.item.ItemStack;
+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.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("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 Storage[] storages = new Storage[STORAGE_SIZE];
+
+ /**
+ * 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) {
+ ScreenEvents.remove(screen).register(screen1 -> updateStorage(handledScreen));
+ }
+ });
+ }
+
+ public static void tick() {
+ Utils.update();