diff options
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock/item')
15 files changed, 214 insertions, 160 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java index b011b2b0..4440cd84 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java @@ -22,8 +22,8 @@ import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallba import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.item.DyeableItem; import net.minecraft.item.ItemStack; +import net.minecraft.registry.tag.ItemTags; import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; @@ -62,7 +62,7 @@ public class CustomArmorAnimatedDyes { ItemStack heldItem = source.getPlayer().getMainHandStack(); if (Utils.isOnSkyblock() && heldItem != null && !heldItem.isEmpty()) { - if (heldItem.getItem() instanceof DyeableItem) { + if (heldItem.isIn(ItemTags.DYEABLE)) { String itemUuid = ItemUtils.getItemUuid(heldItem); if (!itemUuid.isEmpty()) { 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 639e98ed..97311220 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java @@ -12,8 +12,8 @@ import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.item.DyeableItem; import net.minecraft.item.ItemStack; +import net.minecraft.registry.tag.ItemTags; import net.minecraft.text.Text; public class CustomArmorDyeColors { @@ -40,7 +40,7 @@ public class CustomArmorDyeColors { } if (Utils.isOnSkyblock() && heldItem != null) { - if (heldItem.getItem() instanceof DyeableItem) { + if (heldItem.isIn(ItemTags.DYEABLE)) { String itemUuid = ItemUtils.getItemUuid(heldItem); if (!itemUuid.isEmpty()) { 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 3434f026..65e1b138 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java @@ -5,8 +5,8 @@ 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.debug.Debug; import de.hysky.skyblocker.events.SkyblockEvents; import de.hysky.skyblocker.utils.Constants; import de.hysky.skyblocker.utils.ItemUtils; @@ -17,6 +17,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.command.CommandRegistryAccess; @@ -25,20 +26,19 @@ import net.minecraft.command.argument.IdentifierArgumentType; import net.minecraft.item.ArmorItem; import net.minecraft.item.ItemStack; import net.minecraft.item.trim.ArmorTrim; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtOps; +import net.minecraft.item.trim.ArmorTrimMaterial; +import net.minecraft.item.trim.ArmorTrimPattern; import net.minecraft.registry.*; +import net.minecraft.registry.entry.RegistryEntry.Reference; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Optional; - public class CustomArmorTrims { private static final Logger LOGGER = LoggerFactory.getLogger(CustomArmorTrims.class); - public static final Object2ObjectOpenHashMap<ArmorTrimId, Optional<ArmorTrim>> TRIMS_CACHE = new Object2ObjectOpenHashMap<>(); + public static final Object2ObjectOpenHashMap<ArmorTrimId, ArmorTrim> TRIMS_CACHE = new Object2ObjectOpenHashMap<>(); private static boolean trimsInitialized = false; public static void init() { @@ -48,24 +48,18 @@ public class CustomArmorTrims { private static void initializeTrimCache() { ClientPlayerEntity player = MinecraftClient.getInstance().player; - if (trimsInitialized || player == null) { + FabricLoader loader = FabricLoader.getInstance(); + if (trimsInitialized || (player == null && !Debug.debugEnabled())) { return; } try { TRIMS_CACHE.clear(); - DynamicRegistryManager registryManager = player.networkHandler.getRegistryManager(); - for (Identifier material : registryManager.get(RegistryKeys.TRIM_MATERIAL).getIds()) { - for (Identifier pattern : registryManager.get(RegistryKeys.TRIM_PATTERN).getIds()) { - NbtCompound compound = new NbtCompound(); - compound.putString("material", material.toString()); - compound.putString("pattern", pattern.toString()); - - ArmorTrim trim = ArmorTrim.CODEC.parse(RegistryOps.of(NbtOps.INSTANCE, registryManager), compound).resultOrPartial(LOGGER::error).orElse(null); + RegistryWrapper.WrapperLookup wrapperLookup = getWrapperLookup(loader, player); + for (Reference<ArmorTrimMaterial> material : wrapperLookup.getWrapperOrThrow(RegistryKeys.TRIM_MATERIAL).streamEntries().toList()) { + for (Reference<ArmorTrimPattern> pattern : wrapperLookup.getWrapperOrThrow(RegistryKeys.TRIM_PATTERN).streamEntries().toList()) { + ArmorTrim trim = new ArmorTrim(material, pattern); - // Something went terribly wrong - if (trim == null) throw new IllegalStateException("Trim shouldn't be null! [" + "\"" + material + "\",\"" + pattern + "\"]"); - - TRIMS_CACHE.put(new ArmorTrimId(material, pattern), Optional.of(trim)); + TRIMS_CACHE.put(new ArmorTrimId(material.registryKey().getValue(), pattern.registryKey().getValue()), trim); } } @@ -76,6 +70,10 @@ public class CustomArmorTrims { } } + private static RegistryWrapper.WrapperLookup getWrapperLookup(FabricLoader loader, ClientPlayerEntity player) { + return !Debug.debugEnabled() ? player.networkHandler.getRegistryManager() : BuiltinRegistries.createWrapperLookup(); + } + private static void registerCommand(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) { dispatcher.register(ClientCommandManager.literal("skyblocker") .then(ClientCommandManager.literal("custom") 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 e47444cf..e1af788e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomItemNames.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomItemNames.java @@ -26,7 +26,7 @@ public class CustomItemNames { .then(ClientCommandManager.literal("custom") .then(ClientCommandManager.literal("renameItem") .executes(context -> renameItem(context.getSource(), null)) - .then(ClientCommandManager.argument("textComponent", TextArgumentType.text()) + .then(ClientCommandManager.argument("textComponent", TextArgumentType.text(registryAccess)) .executes(context -> renameItem(context.getSource(), context.getArgument("textComponent", Text.class))))))); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java index d4bf3d52..8a23ea6d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java @@ -17,7 +17,6 @@ import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.item.TooltipContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.texture.Sprite; import net.minecraft.item.ItemStack; @@ -48,7 +47,7 @@ public class ItemRarityBackgrounds { ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> { String title = screen.getTitle().getString(); - if (Utils.isOnSkyblock() && (title.equals("The Hex") || title.equals("Craft Item") || title.equals("Anvil") || title.equals("Reforge Anvil"))) { + if (Utils.isOnSkyblock() && (title.contains("The Hex") || title.equals("Craft Item") || title.equals("Anvil") || title.equals("Reforge Anvil"))) { ScreenEvents.remove(screen).register(screen1 -> CACHE.clear()); } }); @@ -74,8 +73,8 @@ public class ItemRarityBackgrounds { if (CACHE.containsKey(hashCode)) return CACHE.get(hashCode); - List<Text> tooltip = stack.getTooltip(player, TooltipContext.BASIC); - String[] stringifiedTooltip = tooltip.stream().map(Text::getString).toArray(String[]::new); + List<Text> lore = ItemUtils.getLore(stack); + String[] stringifiedTooltip = lore.stream().map(Text::getString).toArray(String[]::new); for (String rarityString : LORE_RARITIES.keySet()) { if (Arrays.stream(stringifiedTooltip).anyMatch(line -> line.contains(rarityString))) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java b/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java index ae908245..c78724ca 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java @@ -3,13 +3,16 @@ package de.hysky.skyblocker.skyblock.item; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import com.google.gson.reflect.TypeToken; +import com.mojang.serialization.Codec; +import com.mojang.serialization.JsonOps; +import com.mojang.serialization.codecs.RecordCodecBuilder; 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.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.minecraft.client.MinecraftClient; @@ -21,7 +24,6 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.lang.reflect.Type; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; @@ -32,8 +34,7 @@ import java.util.concurrent.CompletableFuture; 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 final Map<String, Object2ObjectOpenHashMap<String, ProfileMuseumData>> MUSEUM_ITEM_CACHE = new Object2ObjectOpenHashMap<>(); private static final String ERROR_LOG_TEMPLATE = "[Skyblocker] Failed to refresh museum item data for profile {}"; private static CompletableFuture<Void> loaded; @@ -45,7 +46,7 @@ public class MuseumItemCache { 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); + Map<String, Object2ObjectOpenHashMap<String, ProfileMuseumData>> cachedData = ProfileMuseumData.SERIALIZATION_CODEC.parse(JsonOps.INSTANCE, JsonParser.parseReader(reader)).getOrThrow(); MUSEUM_ITEM_CACHE.putAll(cachedData); LOGGER.info("[Skyblocker] Loaded museum items cache"); @@ -59,7 +60,7 @@ public class MuseumItemCache { private static void save() { CompletableFuture.runAsync(() -> { try (BufferedWriter writer = Files.newBufferedWriter(CACHE_FILE)) { - SkyblockerMod.GSON.toJson(MUSEUM_ITEM_CACHE, writer); + SkyblockerMod.GSON.toJson(ProfileMuseumData.SERIALIZATION_CODEC.encodeStart(JsonOps.INSTANCE, MUSEUM_ITEM_CACHE).getOrThrow(), writer); } catch (IOException e) { LOGGER.error("[Skyblocker] Failed to save cached museum items!", e); } @@ -68,7 +69,7 @@ public class MuseumItemCache { private static void updateData4ProfileMember(String uuid, String profileId) { CompletableFuture.runAsync(() -> { - try (ApiResponse response = Http.sendHypixelRequest("skyblock/museum", "?profile=" + profileId)) { + try (ApiResponse response = Http.sendHypixelRequest("skyblock/museum", "?profile=" + profileId)) { //The request was successful if (response.ok()) { JsonObject profileData = JsonParser.parseString(response.content()).getAsJsonObject(); @@ -86,7 +87,7 @@ public class MuseumItemCache { 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)), NbtTagSizeTracker.ofUnlimitedBytes()).getList("i", NbtElement.COMPOUND_TYPE); + NbtList items = NbtIo.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(itemsData)), NbtSizeTracker.ofUnlimitedBytes()).getList("i", NbtElement.COMPOUND_TYPE); for (int i = 0; i < items.size(); i++) { NbtCompound tag = items.getCompound(i).getCompound("tag"); @@ -135,7 +136,7 @@ public class MuseumItemCache { 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, _uuid -> new Object2ObjectOpenHashMap<>()); + Map<String, ProfileMuseumData> playerData = MUSEUM_ITEM_CACHE.computeIfAbsent(uuid, _uuid -> new Object2ObjectOpenHashMap<>()); playerData.putIfAbsent(profileId, ProfileMuseumData.EMPTY); if (playerData.get(profileId).stale()) updateData4ProfileMember(uuid, profileId); @@ -152,6 +153,17 @@ public class MuseumItemCache { 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 static final Codec<ProfileMuseumData> CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.LONG.fieldOf("lastUpdated").forGetter(ProfileMuseumData::lastUpdated), + Codec.STRING.listOf() + .xmap(ObjectOpenHashSet::new, ObjectArrayList::new) + .fieldOf("collectedItemIds") + .forGetter(i -> new ObjectOpenHashSet<>(i.collectedItemIds())) + ).apply(instance, ProfileMuseumData::new)); + //Mojang's internal Codec implementation uses ImmutableMaps so we'll just xmap those away and type safety while we're at it :') + private static final Codec<Map<String, Object2ObjectOpenHashMap<String, ProfileMuseumData>>> SERIALIZATION_CODEC = Codec.unboundedMap(Codec.STRING, Codec.unboundedMap(Codec.STRING, CODEC) + .xmap(Object2ObjectOpenHashMap::new, Object2ObjectOpenHashMap::new) + ).xmap(Object2ObjectOpenHashMap::new, Object2ObjectOpenHashMap::new); private boolean stale() { return System.currentTimeMillis() > lastUpdated + MAX_AGE; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/PlayerHeadHashCache.java b/src/main/java/de/hysky/skyblocker/skyblock/item/PlayerHeadHashCache.java index 2a1688fc..da832164 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/PlayerHeadHashCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/PlayerHeadHashCache.java @@ -1,7 +1,6 @@ package de.hysky.skyblocker.skyblock.item; -import java.net.MalformedURLException; -import java.net.URL; +import java.net.URI; import java.util.Base64; import java.util.concurrent.CompletableFuture; @@ -50,8 +49,8 @@ public class PlayerHeadHashCache { //From MinecraftProfileTexture#getHash public static String getSkinHash(String url) { try { - return FilenameUtils.getBaseName(new URL(url).getPath()); - } catch (MalformedURLException e) { + return FilenameUtils.getBaseName(new URI(url).getPath()); + } catch (Exception e) { LOGGER.error("[Skyblocker Player Head Hash Cache] Malformed Skin URL! URL: {}", url, e); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockCraftingTableScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockCraftingTableScreen.java index 14ddb238..a09b260a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockCraftingTableScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockCraftingTableScreen.java @@ -1,5 +1,7 @@ package de.hysky.skyblocker.skyblock.item; +import java.time.Duration; + import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.itemlist.ItemListWidget; import net.minecraft.client.gui.DrawContext; @@ -21,6 +23,7 @@ import net.minecraft.screen.AbstractRecipeScreenHandler; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.text.OrderedText; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -54,11 +57,13 @@ public class SkyblockCraftingTableScreen extends HandledScreen<SkyblockCraftingT button.setPosition(this.x + 5, this.height / 2 - 49); if (moreCraftsButton != null) moreCraftsButton.setPosition(this.x + 174, this.y + 62); })); - moreCraftsButton = new TexturedButtonWidget(this.x + 174, y + 62, 16, 16, MORE_CRAFTS_TEXTURES, - button -> this.onMouseClick(handler.slots.get(26), handler.slots.get(26).id, 0, SlotActionType.PICKUP)); - moreCraftsButton.setTooltipDelay(250); - moreCraftsButton.setTooltip(Tooltip.of(Text.literal("More Crafts"))); - this.addDrawableChild(moreCraftsButton); + if (!handler.mirrorverse) { + moreCraftsButton = new TexturedButtonWidget(this.x + 174, y + 62, 16, 16, MORE_CRAFTS_TEXTURES, + button -> this.onMouseClick(handler.slots.get(26), handler.slots.get(26).id, 0, SlotActionType.PICKUP)); + moreCraftsButton.setTooltipDelay(Duration.ofMillis(250L)); + moreCraftsButton.setTooltip(Tooltip.of(Text.literal("More Crafts"))); + this.addDrawableChild(moreCraftsButton); + } assert (client != null ? client.player : null) != null; client.player.currentScreenHandler = handler; // recipe book replaces it with the Dummy one fucking DUMBASS this.addSelectableChild(this.recipeBook); @@ -101,7 +106,7 @@ public class SkyblockCraftingTableScreen extends HandledScreen<SkyblockCraftingT int i = this.x; int j = (this.height - this.backgroundHeight) / 2; context.drawTexture(TEXTURE, i, j, 0, 0, this.backgroundWidth, this.backgroundHeight); - context.drawGuiTexture(QUICK_CRAFT, i + 173, j, 0, 25, 84); + if (!handler.mirrorverse) context.drawGuiTexture(QUICK_CRAFT, i + 173, j, 0, 25, 84); } @Override diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockCraftingTableScreenHandler.java b/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockCraftingTableScreenHandler.java index 04974ade..c3704d8c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockCraftingTableScreenHandler.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockCraftingTableScreenHandler.java @@ -1,5 +1,6 @@ package de.hysky.skyblocker.skyblock.item; +import de.hysky.skyblocker.utils.Utils; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; import net.minecraft.screen.GenericContainerScreenHandler; @@ -16,11 +17,22 @@ public class SkyblockCraftingTableScreenHandler extends GenericContainerScreenHa 28, 29, 30, 34 }; + private static final int[] riftNormalSlots = new int[]{ + 11, 12, 13, + 20, 21, 22, 24, + 29, 30, 31 + }; + + public final boolean mirrorverse; + public SkyblockCraftingTableScreenHandler(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory, Inventory inventory, int rows) { super(type, syncId, playerInventory, inventory, rows); + mirrorverse = Utils.getIslandArea().toLowerCase().contains("mirrorverse"); + int[] activeSlots = mirrorverse ? riftNormalSlots: normalSlots; + for (int i = 0; i < rows * 9; i++) { Slot originalSlot = slots.get(i); - if (Arrays.binarySearch(normalSlots, i) >= 0) { + if (Arrays.binarySearch(activeSlots, i) >= 0) { int[] coords = getCoords(i); Slot slot = new Slot(originalSlot.inventory, originalSlot.getIndex(), coords[0], coords[1]); slot.id = i; @@ -45,14 +57,21 @@ public class SkyblockCraftingTableScreenHandler extends GenericContainerScreenHa } private int[] getCoords(int slot) { - if (slot == 23) return new int[]{124, 35}; - if (slot == 16 || slot == 25 || slot == 34) { - int y = (slot / 9 - 1) * 18 + 8; - return new int[]{174, y}; + if (mirrorverse) { + if (slot == 24) return new int[]{124, 35}; + int gridX = slot % 9 - 2; + int gridY = slot / 9 - 1; + return new int[]{30 + gridX * 18, 17 + gridY * 18}; + } else { + if (slot == 23) return new int[]{124, 35}; + if (slot == 16 || slot == 25 || slot == 34) { + int y = (slot / 9 - 1) * 18 + 8; + return new int[]{174, y}; + } + int gridX = slot % 9 - 1; + int gridY = slot / 9 - 1; + return new int[]{30 + gridX * 18, 17 + gridY * 18}; } - int gridX = slot % 9 - 1; - int gridY = slot / 9 - 1; - return new int[]{30 + gridX * 18, 17 + gridY * 18}; } public static class DisabledSlot extends Slot { 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 5815c11f..109e5503 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java @@ -2,7 +2,9 @@ package de.hysky.skyblocker.skyblock.item; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; +import de.hysky.skyblocker.utils.Constants; 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.option.KeyBinding; import net.minecraft.client.util.InputUtil; @@ -10,6 +12,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.screen.slot.Slot; import net.minecraft.text.Text; import net.minecraft.util.Util; +import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFW; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,7 +22,6 @@ import java.util.concurrent.CompletableFuture; public class WikiLookup { private static final Logger LOGGER = LoggerFactory.getLogger(WikiLookup.class); public static KeyBinding wikiLookup; - private static String id; public static void init() { wikiLookup = KeyBindingHelper.registerKeyBinding(new KeyBinding( @@ -30,24 +32,15 @@ public class WikiLookup { )); } - public static void getSkyblockId(Slot slot) { - //Grabbing the skyblock NBT data - ItemUtils.getItemIdOptional(slot.getStack()).ifPresent(newId -> id = newId); - } + public static void openWiki(@NotNull Slot slot, @NotNull PlayerEntity player) { + if (!Utils.isOnSkyblock() || !SkyblockerConfigManager.get().general.wikiLookup.enableWikiLookup) return; - public static void openWiki(Slot slot, PlayerEntity player) { - if (SkyblockerConfigManager.get().general.wikiLookup.enableWikiLookup) { - getSkyblockId(slot); - try { - String wikiLink = ItemRepository.getWikiLink(id, player); - if (wikiLink != null) CompletableFuture.runAsync(() -> Util.getOperatingSystem().open(wikiLink)); - } catch (IndexOutOfBoundsException | IllegalStateException e) { - 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); - } - } - } + ItemUtils.getItemIdOptional(slot.getStack()) + .map(ItemRepository::getWikiLink) + .ifPresentOrElse(wikiLink -> CompletableFuture.runAsync(() -> Util.getOperatingSystem().open(wikiLink)).exceptionally(e -> { + LOGGER.error("[Skyblocker] Error while retrieving wiki article...", e); + player.sendMessage(Constants.PREFIX.get().append("Error while retrieving wiki article, see logs..."), false); + return null; + }), () -> player.sendMessage(Constants.PREFIX.get().append(Text.translatable("skyblocker.wikiLookup.noArticleFound")), false)); } - } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java index b4d47617..06601f80 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java @@ -75,7 +75,7 @@ public class AccessoriesHelper { private static void load() { loaded = CompletableFuture.runAsync(() -> { try (BufferedReader reader = Files.newBufferedReader(FILE)) { - COLLECTED_ACCESSORIES.putAll(ProfileAccessoryData.SERIALIZATION_CODEC.parse(JsonOps.COMPRESSED, JsonParser.parseReader(reader)).result().orElseThrow()); + COLLECTED_ACCESSORIES.putAll(ProfileAccessoryData.SERIALIZATION_CODEC.parse(JsonOps.COMPRESSED, JsonParser.parseReader(reader)).getOrThrow()); } catch (NoSuchFileException ignored) { } catch (Exception e) { LOGGER.error("[Skyblocker Accessory Helper] Failed to load accessory file!", e); @@ -85,7 +85,7 @@ public class AccessoriesHelper { private static void save() { try (BufferedWriter writer = Files.newBufferedWriter(FILE)) { - SkyblockerMod.GSON.toJson(ProfileAccessoryData.SERIALIZATION_CODEC.encodeStart(JsonOps.COMPRESSED, COLLECTED_ACCESSORIES).result().orElseThrow(), writer); + SkyblockerMod.GSON.toJson(ProfileAccessoryData.SERIALIZATION_CODEC.encodeStart(JsonOps.COMPRESSED, COLLECTED_ACCESSORIES).getOrThrow(), writer); } catch (Exception e) { LOGGER.error("[Skyblocker Accessory Helper] Failed to save accessory file!", e); } @@ -166,7 +166,7 @@ public class AccessoriesHelper { static void refreshData(JsonObject data) { try { - ACCESSORY_DATA = Accessory.MAP_CODEC.parse(JsonOps.INSTANCE, data).result().orElseThrow(); + ACCESSORY_DATA = Accessory.MAP_CODEC.parse(JsonOps.INSTANCE, data).getOrThrow(); } catch (Exception e) { LOGGER.error("[Skyblocker Accessory Helper] Failed to parse data!", e); } 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 index 37de58e6..50772789 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java @@ -1,9 +1,13 @@ package de.hysky.skyblocker.skyblock.item.tooltip; import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.ItemProtection; import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; +import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.minecraft.client.MinecraftClient; @@ -15,23 +19,26 @@ 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.nbt.NbtOps; +import net.minecraft.nbt.StringNbtReader; +import net.minecraft.nbt.visitor.StringNbtWriter; import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Objects; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; public class BackpackPreview { private static final Logger LOGGER = LoggerFactory.getLogger(BackpackPreview.class); + private static final Identifier ITEM_PROTECTION = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/item_protection.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+)\\)"); @@ -61,8 +68,13 @@ public class BackpackPreview { String id = MinecraftClient.getInstance().getSession().getUuidOrNull().toString().replaceAll("-", "") + "/" + Utils.getProfileId(); if (!id.equals(loaded)) { saveDir = SkyblockerMod.CONFIG_DIR.resolve("backpack-preview/" + id); - //noinspection ResultOfMethodCallIgnored - saveDir.toFile().mkdirs(); + + try { + Files.createDirectories(saveDir); + } catch (Exception e) { + LOGGER.error("[Skyblocker] Failed to create the backpack preview save directory! Path: {}", saveDir, e); + } + // load storage again because profile id changed loaded = id; loadStorages(); @@ -75,10 +87,10 @@ public class BackpackPreview { storages[index] = null; Path storageFile = saveDir.resolve(index + ".nbt"); if (Files.isRegularFile(storageFile)) { - try { - storages[index] = Storage.fromNbt(Objects.requireNonNull(NbtIo.read(storageFile))); + try (BufferedReader reader = Files.newBufferedReader(storageFile)) { + storages[index] = Storage.CODEC.parse(NbtOps.INSTANCE, StringNbtReader.parse(reader.lines().collect(Collectors.joining()))).getOrThrow(); } catch (Exception e) { - LOGGER.error("Failed to load backpack preview file: " + storageFile.getFileName().toString(), e); + LOGGER.error("Failed to load backpack preview file: {}", storageFile.getFileName().toString(), e); } } } @@ -93,11 +105,12 @@ public class BackpackPreview { } private static void saveStorage(int index) { - try { - NbtIo.write(storages[index].toNbt(), saveDir.resolve(index + ".nbt")); + Path storageFile = saveDir.resolve(index + ".nbt"); + try (BufferedWriter writer = Files.newBufferedWriter(storageFile)) { + writer.write(new StringNbtWriter().apply(Storage.CODEC.encodeStart(NbtOps.INSTANCE, storages[index]).getOrThrow())); storages[index].markClean(); } catch (Exception e) { - LOGGER.error("Failed to save backpack preview file: " + index + ".nbt", e); + LOGGER.error("Failed to save backpack preview file: {}", storageFile.getFileName().toString(), e); } } @@ -105,7 +118,7 @@ public class BackpackPreview { String title = handledScreen.getTitle().getString(); int index = getStorageIndexFromTitle(title); if (index != -1) { - storages[index] = new Storage(handledScreen.getScreenHandler().slots.get(0).inventory, title, true); + storages[index] = new Storage(handledScreen.getScreenHandler().slots.getFirst().inventory, title, true); } } @@ -129,7 +142,7 @@ public class BackpackPreview { context.drawTexture(TEXTURE, x, y + rows * 18 + 17, 0, 215, 176, 7); TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - context.drawText(textRenderer, storages[index].name, x + 8, y + 6, 0x404040, false); + 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) { @@ -141,6 +154,12 @@ public class BackpackPreview { ItemRarityBackgrounds.tryDraw(currentStack, context, itemX, itemY); } + if (ItemProtection.isItemProtected(currentStack)) { + RenderSystem.enableBlend(); + context.drawTexture(ITEM_PROTECTION, itemX, itemY, 0, 0, 16, 16, 16, 16); + RenderSystem.disableBlend(); + } + context.drawItem(currentStack, itemX, itemY); context.drawItemInSlot(textRenderer, currentStack, itemX, itemY); } @@ -159,6 +178,10 @@ public class BackpackPreview { } static class Storage { + private static final Codec<Storage> CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.STRING.fieldOf("name").forGetter(Storage::name), + ItemUtils.EMPTY_ALLOWING_ITEMSTACK_CODEC.listOf().fieldOf("items").forGetter(Storage::getItemList) + ).apply(instance, Storage::create)); private final Inventory inventory; private final String name; private boolean dirty; @@ -169,6 +192,10 @@ public class BackpackPreview { this.dirty = dirty; } + private String name() { + return name; + } + private int size() { return inventory.size(); } @@ -181,23 +208,19 @@ public class BackpackPreview { dirty = 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); + private static Storage create(String name, List<ItemStack> items) { + SimpleInventory inventory = new SimpleInventory(items.toArray(ItemStack[]::new)); + return new Storage(inventory, name, false); } - @NotNull - private NbtCompound toNbt() { - NbtCompound root = new NbtCompound(); - NbtList list = new NbtList(); + private List<ItemStack> getItemList() { + List<ItemStack> items = new ArrayList<>(); + for (int i = 0; i < size(); ++i) { - list.add(getStack(i).writeNbt(new NbtCompound())); + items.add(getStack(i)); } - root.put("list", list); - root.put("size", NbtInt.of(size())); - root.putString("name", name); - return root; + + return items; } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/CompactorDeletorPreview.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/CompactorDeletorPreview.java index 657db0c9..c5279c61 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/CompactorDeletorPreview.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/CompactorDeletorPreview.java @@ -1,6 +1,6 @@ package de.hysky.skyblocker.skyblock.item.tooltip; -import de.hysky.skyblocker.mixin.accessor.DrawContextInvoker; +import de.hysky.skyblocker.mixins.accessors.DrawContextInvoker; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.utils.ItemUtils; import it.unimi.dsi.fastutil.ints.IntIntPair; @@ -40,10 +40,9 @@ public class CompactorDeletorPreview { if (targetIndex == -1) return false; // Get items in compactor or deletor - NbtCompound extraAttributes = ItemUtils.getExtraAttributes(stack); - if (extraAttributes == null) return false; + NbtCompound customData = ItemUtils.getCustomData(stack); // 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)), ItemRepository.getItemStack(extraAttributes.getString(slot)))).toList(); + List<IntObjectPair<ItemStack>> slots = customData.getKeys().stream().filter(slot -> slot.contains(type.toLowerCase().substring(0, 7))).map(slot -> IntObjectPair.of(Integer.parseInt(slot.substring(17)), ItemRepository.getItemStack(customData.getString(slot)))).toList(); List<TooltipComponent> components = tooltips.stream().map(Text::asOrderedText).map(TooltipComponent::of).collect(Collectors.toList()); IntIntPair dimensions = DIMENSIONS.getOrDefault(size, DEFAULT_DIMENSION); @@ -60,9 +59,9 @@ public class CompactorDeletorPreview { // Add the preview tooltip component components.add(targetIndex, new CompactorPreviewTooltipComponent(slots, dimensions)); - if (extraAttributes.contains("PERSONAL_DELETOR_ACTIVE")) { + if (customData.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())); + .append(customData.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; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ExoticTooltip.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ExoticTooltip.java index 66d94890..46babc8b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ExoticTooltip.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ExoticTooltip.java @@ -65,8 +65,8 @@ public class ExoticTooltip { return DyeType.EXOTIC; } - public static boolean intendedDyed(NbtCompound ItemData) { - return ItemData.getCompound("ExtraAttributes").contains("dye_item"); + public static boolean intendedDyed(NbtCompound customData) { + return customData.contains("dye_item"); } public enum DyeType implements StringIdentifiable { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java index ea24dc63..0cffa05c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java @@ -12,14 +12,17 @@ import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.Scheduler; import it.unimi.dsi.fastutil.Pair; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.item.TooltipContext; -import net.minecraft.item.DyeableItem; +import net.minecraft.client.item.TooltipType; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.DyedColorComponent; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; + import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +36,7 @@ public class ItemTooltip { protected static final SkyblockerConfig.ItemTooltip config = SkyblockerConfigManager.get().general.itemTooltip; private static volatile boolean sentNullWarning = false; - public static void getTooltip(ItemStack stack, TooltipContext context, List<Text> lines) { + public static void getTooltip(ItemStack stack, Item.TooltipContext tooltipContext, TooltipType tooltipType, List<Text> lines) { if (!Utils.isOnSkyblock() || client.player == null) return; String name = getInternalNameFromNBT(stack, false); @@ -123,31 +126,31 @@ public class ItemTooltip { } } - final Map<Integer, String> itemTierFloors = new HashMap<>() {{ - put(1, "F1"); - put(2, "F2"); - put(3, "F3"); - put(4, "F4/M1"); - put(5, "F5/M2"); - put(6, "F6/M3"); - put(7, "F7/M4"); - put(8, "M5"); - put(9, "M6"); - put(10, "M7"); - }}; + final Map<Integer, String> itemTierFloors = Map.of( + 1, "F1", + 2, "F2", + 3, "F3", + 4, "F4/M1", + 5, "F5/M2", + 6, "F6/M3", + 7, "F7/M4", + 8, "M5", + 9, "M6", + 10, "M7" + ); if (SkyblockerConfigManager.get().general.dungeonQuality) { - NbtCompound ea = ItemUtils.getExtraAttributes(stack); - if (ea != null && ea.contains("baseStatBoostPercentage")) { - int baseStatBoostPercentage = ea.getInt("baseStatBoostPercentage"); + NbtCompound customData = ItemUtils.getCustomData(stack); + if (customData != null && customData.contains("baseStatBoostPercentage")) { + int baseStatBoostPercentage = customData.getInt("baseStatBoostPercentage"); boolean maxQuality = baseStatBoostPercentage == 50; if (maxQuality) { lines.add(Text.literal(String.format("%-17s", "Item Quality:") + baseStatBoostPercentage + "/50").formatted(Formatting.RED).formatted(Formatting.BOLD)); } else { lines.add(Text.literal(String.format("%-21s", "Item Quality:") + baseStatBoostPercentage + "/50").formatted(Formatting.BLUE)); } - if (ea.contains("item_tier")) { // sometimes it just isn't here? - int itemTier = ea.getInt("item_tier"); + if (customData.contains("item_tier")) { // sometimes it just isn't here? + int itemTier = customData.getInt("item_tier"); if (maxQuality) { lines.add(Text.literal(String.format("%-17s", "Floor Tier:") + itemTier + " (" + itemTierFloors.get(itemTier) + ")").formatted(Formatting.RED).formatted(Formatting.BOLD)); } else { @@ -186,8 +189,8 @@ public class ItemTooltip { lines.add(Text.literal(String.format(format, "Museum: (" + itemCategory + ")")) .formatted(Formatting.LIGHT_PURPLE)); } else { - NbtCompound extraAttributes = ItemUtils.getExtraAttributes(stack); - boolean isInMuseum = (extraAttributes.contains("donated_museum") && extraAttributes.getBoolean("donated_museum")) || MuseumItemCache.hasItemInMuseum(internalID); + NbtCompound customData = ItemUtils.getCustomData(stack); + boolean isInMuseum = (customData.contains("donated_museum") && customData.getBoolean("donated_museum")) || MuseumItemCache.hasItemInMuseum(internalID); Formatting donatedIndicatorFormatting = isInMuseum ? Formatting.GREEN : Formatting.RED; @@ -198,12 +201,16 @@ public class ItemTooltip { } } - if (TooltipInfoType.COLOR.isTooltipEnabledAndHasOrNullWarning(internalID) && stack.getNbt() != null) { + if (TooltipInfoType.COLOR.isTooltipEnabledAndHasOrNullWarning(internalID) && stack.contains(DataComponentTypes.DYED_COLOR)) { String uuid = ItemUtils.getItemUuid(stack); boolean hasCustomDye = SkyblockerConfigManager.get().general.customDyeColors.containsKey(uuid) || SkyblockerConfigManager.get().general.customAnimatedDyes.containsKey(uuid); + //DyedColorComponent#getColor returns ARGB so we mask out the alpha bits + int dyeColor = DyedColorComponent.getColor(stack, 0); - if (!hasCustomDye && stack.getItem() instanceof DyeableItem item && item.hasColor(stack)) { - String colorHex = String.format("%06X", item.getColor(stack)); + // dyeColor will have alpha = 255 if it's dyed, and alpha = 0 if it's not dyed, + if (!hasCustomDye && dyeColor != 0) { + dyeColor = dyeColor & 0x00FFFFFF; + String colorHex = String.format("%06X", dyeColor); String expectedHex = ExoticTooltip.getExpectedHex(internalID); boolean correctLine = false; @@ -212,13 +219,13 @@ public class ItemTooltip { if (existingTooltip.startsWith("Color: ")) { correctLine = true; - addExoticTooltip(lines, internalID, stack.getNbt(), colorHex, expectedHex, existingTooltip); + addExoticTooltip(lines, internalID, ItemUtils.getCustomData(stack), colorHex, expectedHex, existingTooltip); break; } } if (!correctLine) { - addExoticTooltip(lines, internalID, stack.getNbt(), colorHex, expectedHex, ""); + addExoticTooltip(lines, internalID, ItemUtils.getCustomData(stack), colorHex, expectedHex, ""); } } } @@ -271,8 +278,8 @@ public class ItemTooltip { return neuName; } - private static void addExoticTooltip(List<Text> lines, String internalID, NbtCompound nbt, String colorHex, String expectedHex, String existingTooltip) { - if (expectedHex != null && !colorHex.equalsIgnoreCase(expectedHex) && !ExoticTooltip.isException(internalID, colorHex) && !ExoticTooltip.intendedDyed(nbt)) { + private static void addExoticTooltip(List<Text> lines, String internalID, NbtCompound customData, String colorHex, String expectedHex, String existingTooltip) { + if (expectedHex != null && !colorHex.equalsIgnoreCase(expectedHex) && !ExoticTooltip.isException(internalID, colorHex) && !ExoticTooltip.intendedDyed(customData)) { final ExoticTooltip.DyeType type = ExoticTooltip.checkDyeType(colorHex); lines.add(1, Text.literal(existingTooltip + Formatting.DARK_GRAY + "(").append(type.getTranslatedText()).append(Formatting.DARK_GRAY + ")")); } @@ -287,57 +294,57 @@ public class ItemTooltip { // TODO What in the world is this? public static String getInternalNameFromNBT(ItemStack stack, boolean internalIDOnly) { - NbtCompound ea = ItemUtils.getExtraAttributes(stack); + NbtCompound customData = ItemUtils.getCustomData(stack); - if (ea == null || !ea.contains(ItemUtils.ID, NbtElement.STRING_TYPE)) { + if (customData == null || !customData.contains(ItemUtils.ID, NbtElement.STRING_TYPE)) { return null; } - String internalName = ea.getString(ItemUtils.ID); + String internalName = customData.getString(ItemUtils.ID); if (internalIDOnly) { return internalName; } // Transformation to API format. - if (ea.contains("is_shiny")) { + if (customData.contains("is_shiny")) { return "ISSHINY_" + internalName; } switch (internalName) { case "ENCHANTED_BOOK" -> { - if (ea.contains("enchantments")) { - NbtCompound enchants = ea.getCompound("enchantments"); + if (customData.contains("enchantments")) { + NbtCompound enchants = customData.getCompound("enchantments"); Optional<String> firstEnchant = enchants.getKeys().stream().findFirst(); String enchant = firstEnchant.orElse(""); return "ENCHANTMENT_" + enchant.toUpperCase(Locale.ENGLISH) + "_" + enchants.getInt(enchant); } } case "PET" -> { - if (ea.contains("petInfo")) { - JsonObject petInfo = SkyblockerMod.GSON.fromJson(ea.getString("petInfo"), JsonObject.class); + if (customData.contains("petInfo")) { + JsonObject petInfo = SkyblockerMod.GSON.fromJson(customData.getString("petInfo"), JsonObject.class); return "LVL_1_" + petInfo.get("tier").getAsString() + "_" + petInfo.get("type").getAsString(); } } case "POTION" -> { - String enhanced = ea.contains("enhanced") ? "_ENHANCED" : ""; - String extended = ea.contains("extended") ? "_EXTENDED" : ""; - String splash = ea.contains("splash") ? "_SPLASH" : ""; - if (ea.contains("potion") && ea.contains("potion_level")) { - return (ea.getString("potion") + "_" + internalName + "_" + ea.getInt("potion_level") + String enhanced = customData.contains("enhanced") ? "_ENHANCED" : ""; + String extended = customData.contains("extended") ? "_EXTENDED" : ""; + String splash = customData.contains("splash") ? "_SPLASH" : ""; + if (customData.contains("potion") && customData.contains("potion_level")) { + return (customData.getString("potion") + "_" + internalName + "_" + customData.getInt("potion_level") + enhanced + extended + splash).toUpperCase(Locale.ENGLISH); } } case "RUNE" -> { - if (ea.contains("runes")) { - NbtCompound runes = ea.getCompound("runes"); + if (customData.contains("runes")) { + NbtCompound runes = customData.getCompound("runes"); Optional<String> firstRunes = runes.getKeys().stream().findFirst(); String rune = firstRunes.orElse(""); return rune.toUpperCase(Locale.ENGLISH) + "_RUNE_" + runes.getInt(rune); } } case "ATTRIBUTE_SHARD" -> { - if (ea.contains("attributes")) { - NbtCompound shards = ea.getCompound("attributes"); + if (customData.contains("attributes")) { + NbtCompound shards = customData.getCompound("attributes"); Optional<String> firstShards = shards.getKeys().stream().findFirst(); String shard = firstShards.orElse(""); return internalName + "-" + shard.toUpperCase(Locale.ENGLISH) + "_" + shards.getInt(shard); |