From 2b0dbeb3d445e3300361a657f8b1d63644d99cb5 Mon Sep 17 00:00:00 2001 From: Aerh <22944369+Aerhhh@users.noreply.github.com> Date: Wed, 28 May 2025 13:07:53 +0100 Subject: Item Background Refactor + Jacob's Contest Medal Background Colors (#1262) * Refactor item backgrounds, add Jacob's Contest medal background colors * Fix indentation? * ColoredBackgroundStyle -> ItemBackgroundStyle, I like it more * I forgot to rename a few other things * Remove colored from asset names * Forgot to rename the assets here * Screen cache thing is done by the other cache clear method, not this one * No default value of -1 * Remove extra blank line * Translucent background * Remove unnecessary method * Remove redundant cache clear in ItemBackgroundManager * Clean up config category --------- Co-authored-by: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> --- .../config/categories/GeneralCategory.java | 122 +++++++++++---------- .../skyblocker/config/configs/GeneralConfig.java | 23 ++-- .../skyblocker/mixins/HandledScreenMixin.java | 8 +- .../de/hysky/skyblocker/mixins/InGameHudMixin.java | 10 +- .../skyblock/auction/widgets/RarityWidget.java | 4 +- .../skyblock/item/ItemRarityBackgrounds.java | 105 ------------------ .../item/background/ColoredItemBackground.java | 102 +++++++++++++++++ .../item/background/ItemBackgroundManager.java | 52 +++++++++ .../background/adders/ItemRarityBackground.java | 99 +++++++++++++++++ .../background/adders/JacobMedalBackground.java | 71 ++++++++++++ .../skyblock/item/tooltip/BackpackPreview.java | 7 +- .../profileviewer/inventory/Inventory.java | 7 +- .../profileviewer/inventory/PlayerInventory.java | 7 +- 13 files changed, 422 insertions(+), 195 deletions(-) delete mode 100644 src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/item/background/ColoredItemBackground.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/item/background/ItemBackgroundManager.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/item/background/adders/ItemRarityBackground.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/item/background/adders/JacobMedalBackground.java (limited to 'src/main/java/de') diff --git a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java index 24cd4974..3f799cd0 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -205,7 +205,7 @@ public class GeneralCategory { () -> config.general.itemTooltip.enableCraftingCost, newValue -> config.general.itemTooltip.enableCraftingCost = newValue) .addListener((ignored, event) -> { - if (event == OptionEventListener.Event.STATE_CHANGE) CraftPriceTooltip.clearCache(); + if (event == OptionEventListener.Event.STATE_CHANGE) CraftPriceTooltip.clearCache(); }) .controller(ConfigUtils::createEnumCyclingListController) .build()) @@ -283,34 +283,42 @@ public class GeneralCategory { .build()) .build()) - //Item Info Display - .group(OptionGroup.createBuilder() - .name(Text.translatable("skyblocker.config.general.itemInfoDisplay")) - .collapsed(true) - .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemRarityBackgrounds")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemRarityBackgrounds.@Tooltip"))) - .binding(defaults.general.itemInfoDisplay.itemRarityBackgrounds, - () -> config.general.itemInfoDisplay.itemRarityBackgrounds, - newValue -> config.general.itemInfoDisplay.itemRarityBackgrounds = newValue) - .controller(ConfigUtils::createBooleanController) - .build()) - .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemRarityBackgroundStyle")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemRarityBackgroundStyle.@Tooltip"))) - .binding(defaults.general.itemInfoDisplay.itemRarityBackgroundStyle, - () -> config.general.itemInfoDisplay.itemRarityBackgroundStyle, - newValue -> config.general.itemInfoDisplay.itemRarityBackgroundStyle = newValue) - .controller(ConfigUtils::createEnumCyclingListController) - .build()) - .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemRarityBackgroundsOpacity")) - .binding(defaults.general.itemInfoDisplay.itemRarityBackgroundsOpacity, - () -> config.general.itemInfoDisplay.itemRarityBackgroundsOpacity, - newValue -> config.general.itemInfoDisplay.itemRarityBackgroundsOpacity = newValue) - .controller(opt -> FloatSliderControllerBuilder.create(opt).range(0f, 1f).step(0.05f).formatValue(ConfigUtils.FLOAT_TWO_FORMATTER)) - .build()) - .build()) + //Item Info Display + .group(OptionGroup.createBuilder() + .name(Text.translatable("skyblocker.config.general.itemInfoDisplay")) + .collapsed(true) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemBackgroundStyle")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemBackgroundStyle.@Tooltip"))) + .binding(defaults.general.itemInfoDisplay.itemBackgroundStyle, + () -> config.general.itemInfoDisplay.itemBackgroundStyle, + newValue -> config.general.itemInfoDisplay.itemBackgroundStyle = newValue) + .controller(ConfigUtils::createEnumCyclingListController) + .build()) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemBackgroundOpacity")) + .binding(defaults.general.itemInfoDisplay.itemBackgroundOpacity, + () -> config.general.itemInfoDisplay.itemBackgroundOpacity, + newValue -> config.general.itemInfoDisplay.itemBackgroundOpacity = newValue) + .controller(opt -> FloatSliderControllerBuilder.create(opt).range(0f, 1f).step(0.05f).formatValue(ConfigUtils.FLOAT_TWO_FORMATTER)) + .build()) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemRarityBackgrounds")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.general.itemInfoDisplay.itemRarityBackgrounds.@Tooltip"))) + .binding(defaults.general.itemInfoDisplay.itemRarityBackgrounds, + () -> config.general.itemInfoDisplay.itemRarityBackgrounds, + newValue -> config.general.itemInfoDisplay.itemRarityBackgrounds = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.general.itemInfoDisplay.jacobMedalBackgrounds")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.general.itemInfoDisplay.jacobMedalBackgrounds.@Tooltip"))) + .binding(defaults.general.itemInfoDisplay.jacobMedalBackgrounds, + () -> config.general.itemInfoDisplay.jacobMedalBackgrounds, + newValue -> config.general.itemInfoDisplay.jacobMedalBackgrounds = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .build()) //Item Protection .group(OptionGroup.createBuilder() @@ -325,13 +333,13 @@ public class GeneralCategory { .controller(ConfigUtils::createEnumCyclingListController) .build()) .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.general.itemProtection.protectValuableConsumables")) - .description(OptionDescription.of(Text.translatable("skyblocker.config.general.itemProtection.protectValuableConsumables.@Tooltip"))) - .binding(defaults.general.itemProtection.protectValuableConsumables, - () -> config.general.itemProtection.protectValuableConsumables, - newValue -> config.general.itemProtection.protectValuableConsumables = newValue) - .controller(ConfigUtils::createBooleanController) - .build()) + .name(Text.translatable("skyblocker.config.general.itemProtection.protectValuableConsumables")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.general.itemProtection.protectValuableConsumables.@Tooltip"))) + .binding(defaults.general.itemProtection.protectValuableConsumables, + () -> config.general.itemProtection.protectValuableConsumables, + newValue -> config.general.itemProtection.protectValuableConsumables = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) .build()) //Wiki Lookup @@ -379,24 +387,24 @@ public class GeneralCategory { .build()) .build()) - //Hitboxes - .group(OptionGroup.createBuilder() - .name(Text.translatable("skyblocker.config.general.hitbox")) - .collapsed(true) - .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.general.hitbox.oldFarmlandHitbox")) - .binding(defaults.general.hitbox.oldFarmlandHitbox, - () -> config.general.hitbox.oldFarmlandHitbox, - newValue -> config.general.hitbox.oldFarmlandHitbox = newValue) - .controller(ConfigUtils::createBooleanController) - .build()) - .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.general.hitbox.oldLeverHitbox")) - .binding(defaults.general.hitbox.oldLeverHitbox, - () -> config.general.hitbox.oldLeverHitbox, - newValue -> config.general.hitbox.oldLeverHitbox = newValue) - .controller(ConfigUtils::createBooleanController) - .build()) + //Hitboxes + .group(OptionGroup.createBuilder() + .name(Text.translatable("skyblocker.config.general.hitbox")) + .collapsed(true) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.general.hitbox.oldFarmlandHitbox")) + .binding(defaults.general.hitbox.oldFarmlandHitbox, + () -> config.general.hitbox.oldFarmlandHitbox, + newValue -> config.general.hitbox.oldFarmlandHitbox = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.general.hitbox.oldLeverHitbox")) + .binding(defaults.general.hitbox.oldLeverHitbox, + () -> config.general.hitbox.oldLeverHitbox, + newValue -> config.general.hitbox.oldLeverHitbox = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) .option(Option.createBuilder() .name(Text.translatable("skyblocker.config.general.hitbox.oldMushroomHitbox")) .binding(defaults.general.hitbox.oldMushroomHitbox, @@ -404,8 +412,8 @@ public class GeneralCategory { newValue -> config.general.hitbox.oldMushroomHitbox = newValue) .controller(ConfigUtils::createBooleanController) .build()) - .build()) + .build()) - .build(); - } + .build(); + } } diff --git a/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java index e79ea878..2605d5ef 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java @@ -195,29 +195,32 @@ public class GeneralConfig { @SerialEntry public boolean attributeShardInfo = true; - @SerialEntry - public boolean itemRarityBackgrounds = true; + @SerialEntry + public ItemBackgroundStyle itemBackgroundStyle = ItemBackgroundStyle.SQUARE; - @SerialEntry - public RarityBackgroundStyle itemRarityBackgroundStyle = RarityBackgroundStyle.SQUARE; + @SerialEntry + public float itemBackgroundOpacity = 0.5f; @SerialEntry - public float itemRarityBackgroundsOpacity = 1f; + public boolean itemRarityBackgrounds = true; + + @SerialEntry + public boolean jacobMedalBackgrounds = true; } - public enum RarityBackgroundStyle { - CIRCULAR(Identifier.of(SkyblockerMod.NAMESPACE, "item_rarity_background_circular")), - SQUARE(Identifier.of(SkyblockerMod.NAMESPACE, "item_rarity_background_square")); + public enum ItemBackgroundStyle { + CIRCULAR(Identifier.of(SkyblockerMod.NAMESPACE, "item_background_circular")), + SQUARE(Identifier.of(SkyblockerMod.NAMESPACE, "item_background_square")); public final Identifier tex; - RarityBackgroundStyle(Identifier tex) { + ItemBackgroundStyle(Identifier tex) { this.tex = tex; } @Override public String toString() { - return I18n.translate("skyblocker.config.general.itemInfoDisplay.itemRarityBackgroundStyle.style." + name()); + return I18n.translate("skyblocker.config.general.itemInfoDisplay.itemBackgroundStyle.style." + name()); } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java index f3707406..d5734e63 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java @@ -11,6 +11,7 @@ import de.hysky.skyblocker.skyblock.experiment.SuperpairsSolver; import de.hysky.skyblocker.skyblock.experiment.UltrasequencerSolver; import de.hysky.skyblocker.skyblock.garden.visitor.VisitorHelper; import de.hysky.skyblocker.skyblock.item.*; +import de.hysky.skyblocker.skyblock.item.background.ItemBackgroundManager; import de.hysky.skyblocker.skyblock.item.slottext.SlotTextManager; import de.hysky.skyblocker.skyblock.item.tooltip.BackpackPreview; import de.hysky.skyblocker.skyblock.item.tooltip.CompactorDeletorPreview; @@ -329,12 +330,15 @@ public abstract class HandledScreenMixin extends Screen @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V")) private void skyblocker$drawOnItem(DrawContext context, Slot slot, CallbackInfo ci) { - if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) - ItemRarityBackgrounds.tryDraw(slot.getStack(), context, slot.x, slot.y); + if (Utils.isOnSkyblock()) { + ItemBackgroundManager.drawBackgrounds(slot.getStack(), context, slot.x, slot.y); + } + // Item Protection if (ItemProtection.isItemProtected(slot.getStack())) { context.drawTexture(RenderLayer::getGuiTextured, ItemProtection.ITEM_PROTECTION_TEX, slot.x, slot.y, 0, 0, 16, 16, 16, 16); } + // Search // Darken the slots if (InventorySearch.isSearching() && !InventorySearch.slotMatches(slot)) { diff --git a/src/main/java/de/hysky/skyblocker/mixins/InGameHudMixin.java b/src/main/java/de/hysky/skyblocker/mixins/InGameHudMixin.java index d9520ce4..192cfedd 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/InGameHudMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/InGameHudMixin.java @@ -8,7 +8,7 @@ import de.hysky.skyblocker.skyblock.fancybars.FancyStatusBars; import de.hysky.skyblocker.skyblock.item.HotbarSlotLock; import de.hysky.skyblocker.skyblock.item.ItemCooldowns; import de.hysky.skyblocker.skyblock.item.ItemProtection; -import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; +import de.hysky.skyblocker.skyblock.item.background.ItemBackgroundManager; import de.hysky.skyblocker.skyblock.tabhud.TabHud; import de.hysky.skyblocker.skyblock.tabhud.config.WidgetsConfigurationScreen; import de.hysky.skyblocker.utils.Utils; @@ -52,13 +52,15 @@ public abstract class InGameHudMixin { private MinecraftClient client; @Inject(method = "renderHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHotbarItem(Lnet/minecraft/client/gui/DrawContext;IILnet/minecraft/client/render/RenderTickCounter;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;I)V", ordinal = 0)) - public void skyblocker$renderHotbarItemLockOrRarityBg(CallbackInfo ci, @Local(argsOnly = true) DrawContext context, @Local(ordinal = 4, name = "m") int index, @Local(ordinal = 5, name = "n") int x, @Local(ordinal = 6, name = "o") int y, @Local PlayerEntity player) { + public void skyblocker$renderHotbarItemLockOrBackground(CallbackInfo ci, @Local(argsOnly = true) DrawContext context, @Local(ordinal = 4, name = "m") int index, @Local(ordinal = 5, name = "n") int x, @Local(ordinal = 6, name = "o") int y, @Local PlayerEntity player) { if (Utils.isOnSkyblock()) { - // slot lock - if (SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) ItemRarityBackgrounds.tryDraw(player.getInventory().getMainStacks().get(index), context, x, y); + ItemBackgroundManager.drawBackgrounds(player.getInventory().getMainStacks().get(index), context, x, y); + + // slot lock if (HotbarSlotLock.isLocked(index)) { context.drawTexture(RenderLayer::getGuiTextured, SLOT_LOCK_ICON.get(), x, y, 0, 0, 16, 16, 16, 16); } + //item protection if (ItemProtection.isItemProtected(player.getInventory().getMainStacks().get(index))) { context.drawTexture(RenderLayer::getGuiTextured, ItemProtection.ITEM_PROTECTION_TEX, x, y, 0, 0, 16, 16, 16, 16); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/RarityWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/RarityWidget.java index 483fd458..0f4b309b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/RarityWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/auction/widgets/RarityWidget.java @@ -2,8 +2,8 @@ package de.hysky.skyblocker.skyblock.auction.widgets; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.auction.SlotClickHandler; -import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; import de.hysky.skyblocker.skyblock.item.SkyblockItemRarity; +import de.hysky.skyblocker.skyblock.item.background.adders.ItemRarityBackground; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; @@ -84,7 +84,7 @@ public class RarityWidget extends ClickableWidget { public void setText(List tooltip, String current) { this.tooltip = tooltip; this.current = current; - for (Map.Entry rarity : ItemRarityBackgrounds.LORE_RARITIES.entrySet()) { + for (Map.Entry rarity : ItemRarityBackground.LORE_RARITIES.entrySet()) { if (current.toUpperCase().contains(rarity.getKey())) { this.color = rarity.getValue().color | 0xFF000000; return; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java deleted file mode 100644 index e778191f..00000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java +++ /dev/null @@ -1,105 +0,0 @@ -package de.hysky.skyblocker.skyblock.item; - -import com.google.common.collect.ImmutableMap; -import de.hysky.skyblocker.annotations.Init; -import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.config.configs.GeneralConfig; -import de.hysky.skyblocker.utils.ItemUtils; -import de.hysky.skyblocker.utils.Utils; -import de.hysky.skyblocker.utils.scheduler.Scheduler; -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.render.RenderLayer; -import net.minecraft.client.texture.Sprite; -import net.minecraft.item.ItemStack; -import net.minecraft.text.Text; -import net.minecraft.util.math.ColorHelper; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -public class ItemRarityBackgrounds { - private static final GeneralConfig.ItemInfoDisplay CONFIG = SkyblockerConfigManager.get().general.itemInfoDisplay; - private static final Supplier SPRITE = () -> MinecraftClient.getInstance().getGuiAtlasManager().getSprite(CONFIG.itemRarityBackgroundStyle.tex); - public static final ImmutableMap LORE_RARITIES = ImmutableMap.ofEntries( - Map.entry("ADMIN", SkyblockItemRarity.ADMIN), - Map.entry("ULTIMATE", SkyblockItemRarity.ULTIMATE), - Map.entry("SPECIAL", SkyblockItemRarity.SPECIAL), //Very special is the same color so this will cover it - Map.entry("DIVINE", SkyblockItemRarity.DIVINE), - Map.entry("MYTHIC", SkyblockItemRarity.MYTHIC), - Map.entry("LEGENDARY", SkyblockItemRarity.LEGENDARY), - Map.entry("LEGENJERRY", SkyblockItemRarity.LEGENDARY), - Map.entry("EPIC", SkyblockItemRarity.EPIC), - Map.entry("RARE", SkyblockItemRarity.RARE), - Map.entry("UNCOMMON", SkyblockItemRarity.UNCOMMON), - Map.entry("COMMON", SkyblockItemRarity.COMMON)); - private static final Int2ReferenceOpenHashMap CACHE = new Int2ReferenceOpenHashMap<>(); - - @Init - public static void init() { - //Clear the cache every 5 minutes, ints are very compact! - Scheduler.INSTANCE.scheduleCyclic(CACHE::clear, 4800); - - //Clear cache after a screen where items can be upgraded in rarity closes - ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> { - String title = screen.getTitle().getString(); - - 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()); - } - }); - } - - public static void tryDraw(ItemStack stack, DrawContext context, int x, int y) { - SkyblockItemRarity itemRarity = getItemRarity(stack); - if (itemRarity != null) - draw(context, x, y, itemRarity); - } - - private static SkyblockItemRarity getItemRarity(ItemStack stack) { - if (stack == null || stack.isEmpty()) return null; - - String itemUuid = stack.getUuid(); - - //If the item has an uuid, then use the hash code of the uuid otherwise use the identity hash code of the stack - int hashCode = itemUuid.isEmpty() ? System.identityHashCode(stack) : itemUuid.hashCode(); - - if (CACHE.containsKey(hashCode)) return CACHE.get(hashCode); - - //For regular items check the lore, for pets we use the rarity in the petInfo so that the rarity background work in the pets menu - if (!stack.getSkyblockId().equals("PET")) { - List 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))) { - SkyblockItemRarity rarity = LORE_RARITIES.get(rarityString); - - CACHE.put(hashCode, rarity); - return rarity; - } - } - } else { - PetInfo info = stack.getPetInfo(); - if (!info.isEmpty()) { - SkyblockItemRarity rarity = info.rarity(); - if (info.item().isPresent() && info.item().get().equals("PET_ITEM_TIER_BOOST")) { - rarity = rarity.next(); - } - CACHE.put(hashCode, rarity); - return rarity; - } - } - - CACHE.put(hashCode, null); - return null; - } - - private static void draw(DrawContext context, int x, int y, SkyblockItemRarity rarity) { - context.drawSpriteStretched(RenderLayer::getGuiTextured, SPRITE.get(), x, y, 16, 16, ColorHelper.fromFloats(SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgroundsOpacity, rarity.r, rarity.g, rarity.b)); - } -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/background/ColoredItemBackground.java b/src/main/java/de/hysky/skyblocker/skyblock/item/background/ColoredItemBackground.java new file mode 100644 index 00000000..9c69ca78 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/background/ColoredItemBackground.java @@ -0,0 +1,102 @@ +package de.hysky.skyblocker.skyblock.item.background; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.texture.Sprite; +import net.minecraft.item.ItemStack; + +import java.util.function.Supplier; + +/** + * Base class for rendering colored backgrounds behind Minecraft items. + * Subclasses should implement {@link #getColorKey}, {@link #draw}, and optionally + * {@link #onScreenChange} and {@link #isEnabled} for per-background logic. + * + * @param The key type used to determine what color to render, e.g. an enum or Integer RGB. + */ +public abstract class ColoredItemBackground { + + private final Int2ReferenceOpenHashMap cache = new Int2ReferenceOpenHashMap<>(); + private final Supplier sprite; + + protected ColoredItemBackground() { + this.sprite = () -> MinecraftClient.getInstance() + .getGuiAtlasManager() + .getSprite(SkyblockerConfigManager.get().general.itemInfoDisplay.itemBackgroundStyle.tex); + } + + /** + * Called when a new screen is initialized. Subclasses can use this to register + * screen-specific behavior when the screen is opened. + * + * @param title The screen's title text + * @param screen The {@link Screen screen} instance itself + */ + protected void onScreenChange(String title, Screen screen) { + // Default implementation does nothing + } + + /** + * Determines the color key (e.g. {@link de.hysky.skyblocker.skyblock.item.SkyblockItemRarity} enum or RGB int) + * to use for the given item. + * + * @param stack The item to inspect + * @param cache The internal cache used to store/reuse results + * @return A non-null color key if a background should be drawn, or null to skip rendering + */ + protected abstract T getColorKey(ItemStack stack, Int2ReferenceOpenHashMap cache); + + /** + * Performs the actual background rendering using the resolved color key. + * + * @param context The rendering context + * @param x Slot x position + * @param y Slot y position + * @param colorKey The color key, e.g. an enum or RGB integer + */ + protected abstract void draw(DrawContext context, int x, int y, T colorKey); + + /** + * Whether this background renderer is enabled. + * + * @return True if the background should be rendered, false otherwise. + */ + public boolean isEnabled() { + return true; + } + + /** + * Attempts to draw a background for the given {@link ItemStack} if a valid color + * key is found. + * + * @param stack The {@link ItemStack} to check + * @param context The rendering context + * @param x The slot's x position + * @param y The slot's y position + */ + public final void tryDraw(ItemStack stack, DrawContext context, int x, int y) { + T value = getColorKey(stack, cache); + if (value != null) { + draw(context, x, y, value); + } + } + + /** + * Clears the internal cache manually. + */ + protected final void clearCache() { + cache.clear(); + } + + /** + * Returns the current background sprite for this renderer. + * + * @return The sprite to render with + */ + protected final Sprite getSprite() { + return sprite.get(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/background/ItemBackgroundManager.java b/src/main/java/de/hysky/skyblocker/skyblock/item/background/ItemBackgroundManager.java new file mode 100644 index 00000000..aa23ef79 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/background/ItemBackgroundManager.java @@ -0,0 +1,52 @@ +package de.hysky.skyblocker.skyblock.item.background; + +import de.hysky.skyblocker.annotations.Init; +import de.hysky.skyblocker.skyblock.item.background.adders.ItemRarityBackground; +import de.hysky.skyblocker.skyblock.item.background.adders.JacobMedalBackground; +import de.hysky.skyblocker.utils.scheduler.Scheduler; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.item.ItemStack; + +import java.util.List; + +public class ItemBackgroundManager { + + private static final List> BACKGROUNDS = List.of( + new ItemRarityBackground(), + new JacobMedalBackground() + ); + + @Init + public static void init() { + // Clear the cache of every background every 5 minutes + for (ColoredItemBackground background : BACKGROUNDS) { + Scheduler.INSTANCE.scheduleCyclic(background::clearCache, 6000); + } + + // Hook into screen changes for per-background logic + ScreenEvents.BEFORE_INIT.register((client, screen, width, height) -> { + String title = screen.getTitle().getString(); + + for (ColoredItemBackground background : BACKGROUNDS) { + background.onScreenChange(title, screen); + } + }); + } + + /** + * Attempts to draw all enabled item backgrounds on a single {@link ItemStack}. + * + * @param stack The {@link ItemStack} to check + * @param context The {@link DrawContext} to use for rendering + * @param x X position of the item + * @param y Y position of the item + */ + public static void drawBackgrounds(ItemStack stack, DrawContext context, int x, int y) { + for (ColoredItemBackground background : BACKGROUNDS) { + if (background.isEnabled()) { + background.tryDraw(stack, context, x, y); + } + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/background/adders/ItemRarityBackground.java b/src/main/java/de/hysky/skyblocker/skyblock/item/background/adders/ItemRarityBackground.java new file mode 100644 index 00000000..54b72d52 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/background/adders/ItemRarityBackground.java @@ -0,0 +1,99 @@ +package de.hysky.skyblocker.skyblock.item.background.adders; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.PetInfo; +import de.hysky.skyblocker.skyblock.item.SkyblockItemRarity; +import de.hysky.skyblocker.skyblock.item.background.ColoredItemBackground; +import de.hysky.skyblocker.utils.ItemUtils; +import de.hysky.skyblocker.utils.Utils; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.math.ColorHelper; + +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +public class ItemRarityBackground extends ColoredItemBackground { + + public static final ImmutableMap LORE_RARITIES = ImmutableMap.ofEntries( + Map.entry("ADMIN", SkyblockItemRarity.ADMIN), + Map.entry("ULTIMATE", SkyblockItemRarity.ULTIMATE), + Map.entry("SPECIAL", SkyblockItemRarity.SPECIAL), //Very special is the same color so this will cover it + Map.entry("DIVINE", SkyblockItemRarity.DIVINE), + Map.entry("MYTHIC", SkyblockItemRarity.MYTHIC), + Map.entry("LEGENDARY", SkyblockItemRarity.LEGENDARY), + Map.entry("LEGENJERRY", SkyblockItemRarity.LEGENDARY), + Map.entry("EPIC", SkyblockItemRarity.EPIC), + Map.entry("RARE", SkyblockItemRarity.RARE), + Map.entry("UNCOMMON", SkyblockItemRarity.UNCOMMON), + Map.entry("COMMON", SkyblockItemRarity.COMMON) + ); + + private static final ImmutableList> INVENTORY_TITLES = ImmutableList.of( + title -> title.contains("The Hex"), + title -> title.equals("Craft Item"), + title -> title.equals("Anvil"), + title -> title.equals("Reforge Anvil") + ); + + @Override + public boolean isEnabled() { + return SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds; + } + + @Override + protected SkyblockItemRarity getColorKey(ItemStack stack, Int2ReferenceOpenHashMap cache) { + if (stack == null || stack.isEmpty()) return null; + + int hashCode = stack.getUuid().isEmpty() ? System.identityHashCode(stack) : stack.getUuid().hashCode(); + if (cache.containsKey(hashCode)) return cache.get(hashCode); + + if (!stack.getSkyblockId().equals("PET")) { + List lore = ItemUtils.getLore(stack); + List tooltip = lore.stream().map(Text::getString).toList(); + for (String key : LORE_RARITIES.keySet()) { + if (tooltip.stream().anyMatch(line -> line.contains(key))) { + SkyblockItemRarity rarity = LORE_RARITIES.get(key); + cache.put(hashCode, rarity); + return rarity; + } + } + } else { + PetInfo info = stack.getPetInfo(); + if (!info.isEmpty()) { + SkyblockItemRarity rarity = info.item().isPresent() && info.item().get().equals("PET_ITEM_TIER_BOOST") ? info.rarity().next() : info.rarity(); + cache.put(hashCode, rarity); + return rarity; + } + } + + cache.put(hashCode, null); + return null; + } + + @Override + protected void draw(DrawContext context, int x, int y, SkyblockItemRarity rarity) { + context.drawSpriteStretched(RenderLayer::getGuiTextured, getSprite(), x, y, 16, 16, + ColorHelper.fromFloats( + SkyblockerConfigManager.get().general.itemInfoDisplay.itemBackgroundOpacity, + rarity.r, rarity.g, rarity.b + ) + ); + } + + @Override + protected void onScreenChange(String title, Screen screen) { + if (Utils.isOnSkyblock() && INVENTORY_TITLES.stream().anyMatch(predicate -> predicate.test(title))) { + ScreenEvents.remove(screen).register(s -> clearCache()); + } + } +} + diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/background/adders/JacobMedalBackground.java b/src/main/java/de/hysky/skyblocker/skyblock/item/background/adders/JacobMedalBackground.java new file mode 100644 index 00000000..b340ffa2 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/background/adders/JacobMedalBackground.java @@ -0,0 +1,71 @@ +package de.hysky.skyblocker.skyblock.item.background.adders; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.background.ColoredItemBackground; +import de.hysky.skyblocker.utils.ItemUtils; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.ColorHelper; + +import java.util.Map; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class JacobMedalBackground extends ColoredItemBackground { + + private static final Pattern PATTERN = Pattern.compile("You placed in the (?DIAMOND|PLATINUM|GOLD|SILVER|BRONZE) bracket!"); + private static final Map BRACKET_COLORS = Map.of( + "DIAMOND", Objects.requireNonNull(Formatting.AQUA.getColorValue()), + "PLATINUM", Objects.requireNonNull(Formatting.DARK_AQUA.getColorValue()), + "GOLD", Objects.requireNonNull(Formatting.GOLD.getColorValue()), + "SILVER", Objects.requireNonNull(Formatting.WHITE.getColorValue()), + "BRONZE", Objects.requireNonNull(Formatting.RED.getColorValue()) + ); + + @Override + public boolean isEnabled() { + return SkyblockerConfigManager.get().general.itemInfoDisplay.jacobMedalBackgrounds; + } + + @Override + protected Integer getColorKey(ItemStack stack, Int2ReferenceOpenHashMap cache) { + if (stack == null || stack.isEmpty()) { + return null; + } + + int hashCode = stack.getUuid().isEmpty() ? System.identityHashCode(stack) : stack.getUuid().hashCode(); + if (cache.containsKey(hashCode)) { + return cache.get(hashCode); + } + + Matcher matcher = ItemUtils.getLoreLineIfMatch(stack, PATTERN); + if (matcher != null) { + Integer color = BRACKET_COLORS.get(matcher.group("bracket")); + if (color != null) { + cache.put(hashCode, color); + return color; + } + } + + cache.put(hashCode, null); + return null; + } + + @Override + protected void draw(DrawContext context, int x, int y, Integer color) { + float r = ((color >> 16) & 0xFF) / 255F; + float g = ((color >> 8) & 0xFF) / 255F; + float b = (color & 0xFF) / 255F; + + context.drawSpriteStretched(RenderLayer::getGuiTextured, getSprite(), x, y, 16, 16, + ColorHelper.fromFloats( + SkyblockerConfigManager.get().general.itemInfoDisplay.itemBackgroundOpacity, + r, g, b + ) + ); + } +} 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 2fc1ecff..722b2764 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 @@ -4,9 +4,8 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.annotations.Init; -import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.item.ItemProtection; -import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; +import de.hysky.skyblocker.skyblock.item.background.ItemBackgroundManager; import de.hysky.skyblocker.skyblock.item.slottext.SlotTextManager; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; @@ -157,9 +156,7 @@ public class BackpackPreview { int itemX = x + (i - 9) % 9 * 18 + 8; int itemY = y + (i - 9) / 9 * 18 + 18; - if (SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) { - ItemRarityBackgrounds.tryDraw(currentStack, context, itemX, itemY); - } + ItemBackgroundManager.drawBackgrounds(currentStack, context, itemX, itemY); if (ItemProtection.isItemProtected(currentStack)) { context.drawTexture(RenderLayer::getGuiTextured, ItemProtection.ITEM_PROTECTION_TEX, itemX, itemY, 0, 0, 16, 16, 16, 16); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Inventory.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Inventory.java index 68887273..c5d4d7ad 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Inventory.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Inventory.java @@ -2,9 +2,8 @@ package de.hysky.skyblocker.skyblock.profileviewer.inventory; import com.google.gson.JsonObject; -import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.item.ItemProtection; -import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; +import de.hysky.skyblocker.skyblock.item.background.ItemBackgroundManager; import de.hysky.skyblocker.skyblock.item.slottext.SlotTextManager; import de.hysky.skyblocker.skyblock.profileviewer.ProfileViewerPage; import de.hysky.skyblocker.skyblock.profileviewer.inventory.itemLoaders.ItemLoader; @@ -85,9 +84,7 @@ public class Inventory implements ProfileViewerPage { int x = rootX + 8 + column * 18; int y = rootYAdjusted + 18 + row * 18; - if (SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) { - ItemRarityBackgrounds.tryDraw(stack, context, x, y); - } + ItemBackgroundManager.drawBackgrounds(stack, context, x, y); if (ItemProtection.isItemProtected(stack)) { context.drawTexture(RenderLayer::getGuiTextured, ItemProtection.ITEM_PROTECTION_TEX, x, y, 0, 0, 16, 16, 16, 16); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/PlayerInventory.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/PlayerInventory.java index 30530f48..28c890ae 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/PlayerInventory.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/PlayerInventory.java @@ -2,9 +2,8 @@ package de.hysky.skyblocker.skyblock.profileviewer.inventory; import com.google.gson.JsonObject; -import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.item.ItemProtection; -import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; +import de.hysky.skyblocker.skyblock.item.background.ItemBackgroundManager; import de.hysky.skyblocker.skyblock.item.slottext.SlotTextManager; import de.hysky.skyblocker.skyblock.profileviewer.ProfileViewerPage; import de.hysky.skyblocker.skyblock.profileviewer.inventory.itemLoaders.InventoryItemLoader; @@ -74,9 +73,7 @@ public class PlayerInventory implements ProfileViewerPage { int x = rootX + 8 + column * 18; int y = (rootY + 18 + row * 18) + (dimensions.leftInt() > 1 && row + 1 == dimensions.leftInt() ? 4 : 0); - if (SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) { - ItemRarityBackgrounds.tryDraw(stack, context, x, y); - } + ItemBackgroundManager.drawBackgrounds(stack, context, x, y); if (ItemProtection.isItemProtected(stack)) { context.drawTexture(RenderLayer::getGuiTextured, ItemProtection.ITEM_PROTECTION_TEX, x, y, 0, 0, 16, 16, 16, 16); -- cgit