From 1865310636fffaffad45ee0a127dcceb227e2613 Mon Sep 17 00:00:00 2001 From: LJNeon <23249107+LJNeon@users.noreply.github.com> Date: Wed, 11 Feb 2026 19:02:09 -0700 Subject: [PATCH 1/8] Add option for Stereo Harmony to color pests differently --- .../config/categories/FarmingCategory.java | 8 ++ .../config/configs/FarmingConfig.java | 2 + .../mixins/AbstractContainerScreenMixin.java | 40 ++++---- .../skyblocker/skyblock/VacuumCache.java | 91 +++++++++++++++++++ .../entity/glow/adder/GardenGlowAdder.java | 38 ++++++-- .../assets/skyblocker/lang/en_us.json | 4 +- 6 files changed, 160 insertions(+), 23 deletions(-) create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java diff --git a/src/main/java/de/hysky/skyblocker/config/categories/FarmingCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/FarmingCategory.java index 0a8286ed560..1e5be31e13f 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/FarmingCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/FarmingCategory.java @@ -60,6 +60,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig newValue -> config.farming.garden.pestHighlighter = newValue) .controller(ConfigUtils.createBooleanController()) .build()) + .option(Option.createBuilder() + .name(Component.translatable("skyblocker.config.farming.garden.vinylHighlighter")) + .description(Component.translatable("skyblocker.config.farming.garden.vinylHighlighter.@Tooltip")) + .binding(defaults.farming.garden.vinylHighlighter, + () -> config.farming.garden.vinylHighlighter, + newValue -> config.farming.garden.vinylHighlighter = newValue) + .controller(ConfigUtils.createBooleanController()) + .build()) .option(Option.createBuilder() .name(Component.translatable("skyblocker.config.farming.garden.lockMouseTool")) .binding(defaults.farming.garden.lockMouseTool, diff --git a/src/main/java/de/hysky/skyblocker/config/configs/FarmingConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/FarmingConfig.java index 47baf5740e2..658bd04aa46 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/FarmingConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/FarmingConfig.java @@ -14,6 +14,8 @@ public static class Garden { public boolean pestHighlighter = true; + public boolean vinylHighlighter = true; + public boolean lockMouseTool = false; public boolean lockMouseGroundOnly = false; diff --git a/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java index b96d1a56ac3..4112be9bb21 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java @@ -1,14 +1,33 @@ package de.hysky.skyblocker.mixins; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Matcher; + +import org.jspecify.annotations.Nullable; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.datafixers.util.Either; + import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.InventorySearch; import de.hysky.skyblocker.skyblock.PetCache; +import de.hysky.skyblocker.skyblock.VacuumCache; import de.hysky.skyblocker.skyblock.experiment.UltrasequencerSolver; import de.hysky.skyblocker.skyblock.garden.visitor.VisitorHelper; import de.hysky.skyblocker.skyblock.item.ItemPrice; @@ -48,22 +67,6 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; -import org.jspecify.annotations.Nullable; -import org.lwjgl.glfw.GLFW; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.regex.Matcher; @Mixin(AbstractContainerScreen.class) public abstract class AbstractContainerScreenMixin extends Screen { @@ -388,6 +391,11 @@ protected AbstractContainerScreenMixin(Component title) { PetCache.handlePetEquip(slot, slotId); } + // Vacuum Vinyl Caching + if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && title.startsWith("Stereo Harmony")) { + VacuumCache.handleVinylSelect(slot, slotId); + } + if (currentSolver != null) { boolean disallowed = ContainerSolverManager.onSlotClick(slotId, stack, button); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java b/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java new file mode 100644 index 00000000000..4a69d3aff72 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java @@ -0,0 +1,91 @@ +package de.hysky.skyblocker.skyblock; + + +import java.nio.file.Path; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.jspecify.annotations.Nullable; + +import com.mojang.serialization.Codec; + +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.annotations.Init; +import de.hysky.skyblocker.utils.ItemUtils; +import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.data.ProfiledData; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.screens.inventory.ContainerScreen; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +public class VacuumCache { + private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("vacuum_cache.json"); + private static final ProfiledData CACHED_VINYL = new ProfiledData<>(FILE, Codec.STRING); + private static final Pattern VINYL_PATTERN = Pattern.compile("^When playing, (?[\\w\\s]+) Pests"); + + private VacuumCache() {} + + @Init + public static void init() { + CACHED_VINYL.load(); + + ScreenEvents.BEFORE_INIT.register((_client, screen, _scaledWidth, _scaledHeight) -> { + if (Utils.isOnSkyblock() && screen instanceof ContainerScreen genericContainerScreen) { + if (genericContainerScreen.getTitle().getString().startsWith("Stereo Harmony")) { + ScreenEvents.afterTick(screen).register(screen1 -> { + for (Slot slot : genericContainerScreen.getMenu().slots) { + ItemStack stack = slot.getItem(); + + if (!stack.isEmpty() && ItemUtils.getLoreLineIf(stack, line -> line.equals("Click to stop playing!")) != null) { + parseVinyl(stack, false); + + break; + } + } + }); + } + } + }); + } + + public static void handleVinylSelect(Slot slot, int slotId) { + ItemStack stack = slot.getItem(); + + if (!stack.isEmpty()) parseVinyl(stack, true); + } + + private static void parseVinyl(ItemStack stack, boolean clicked) { + String profileId = Utils.getProfileId(); + + if (stack.getSkyblockId().startsWith("VINYL_") && !profileId.isEmpty()) { + @Nullable String vinyl = null; + + for (String line : stack.skyblocker$getLoreStrings()) { + String stringified = ChatFormatting.stripFormatting(line); + Matcher matcher = VINYL_PATTERN.matcher(stringified); + + if (matcher.matches()) { + vinyl = matcher.group("vinyl"); + + break; + } + } + + if (vinyl == null) return; + + if (clicked && getVinyl() != null && ItemUtils.getLoreLineIf(stack, line -> line.equals("Click to stop playing!")) != null) { + CACHED_VINYL.remove(); + } else { + CACHED_VINYL.put(vinyl); + } + + CACHED_VINYL.save(); + } + } + + public static @Nullable String getVinyl() { + return CACHED_VINYL.get(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java index 79aaee633a7..db452b74c7c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java @@ -3,14 +3,13 @@ import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.minecraft.ChatFormatting; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.decoration.ArmorStand; + import org.apache.commons.lang3.StringUtils; +import org.jspecify.annotations.Nullable; import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.VacuumCache; import de.hysky.skyblocker.skyblock.entity.MobGlowAdder; import de.hysky.skyblocker.skyblock.garden.CurrentJacobCrop; import de.hysky.skyblocker.skyblock.garden.GardenConstants; @@ -18,6 +17,10 @@ import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.Scheduler; +import net.minecraft.ChatFormatting; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.decoration.ArmorStand; public class GardenGlowAdder extends MobGlowAdder { private static final GardenGlowAdder INSTANCE = new GardenGlowAdder(); @@ -36,8 +39,11 @@ case ArmorStand as when isPestHead(as) -> doesPestMatchCurrentContest(as) ? // Pests but during Jacob's Contest ChatFormatting.GREEN.getColor() : - // Default color - PEST_COLOUR; + // Pests from currently playing vinyl + doesPestMatchCurrentVinyl(as) ? + ChatFormatting.AQUA.getColor() : + // Default color + PEST_COLOUR; default -> NO_GLOW; }; } @@ -89,4 +95,24 @@ public static boolean doesPestMatchCurrentContest(ArmorStand entity) { .get(CurrentJacobCrop.CURRENT_CROP_CONTEST) .contains(ItemUtils.getHeadTexture(entity.getItemBySlot(EquipmentSlot.HEAD))); } + + /** + * Matches the armor stand head with currently playing vinyl outside of Jacob's Contest. + */ + public static boolean doesPestMatchCurrentVinyl(ArmorStand entity) { + if (!SkyblockerConfigManager.get().farming.garden.vinylHighlighter) + return false; + + @Nullable String vinyl = VacuumCache.getVinyl(); + + // Only applies outside of Jacob's Contests + if (!StringUtils.isEmpty(CurrentJacobCrop.CURRENT_CROP_CONTEST) || vinyl == null) { + return false; + } + + // Filter only pest head that matches by name + return entity.hasItemInSlot(EquipmentSlot.HEAD) && GardenConstants.PEST_HEAD_BY_CROP + .get(GardenConstants.CROP_BY_PEST.get(vinyl)) + .contains(ItemUtils.getHeadTexture(entity.getItemBySlot(EquipmentSlot.HEAD))); + } } diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index 948f0c23475..5ec97cce4d8 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -455,7 +455,9 @@ "skyblocker.config.farming.garden.lockMouseGround": "Only lock camera when on the ground", "skyblocker.config.farming.garden.lockMouseTool": "Lock camera when holding a farming tool", "skyblocker.config.farming.garden.pestHighlighter": "Pest Highlighter", - "skyblocker.config.farming.garden.pestHighlighter.@Tooltip": "Makes all pests on your island glow so you can see them easier :D", + "skyblocker.config.farming.garden.pestHighlighter.@Tooltip": "Make's all pest's on your island glow so you can see them easier :D", + "skyblocker.config.farming.garden.vinylHighlighter": "Stereo Harmony Vinyl Highlighter", + "skyblocker.config.farming.garden.vinylHighlighter.@Tooltip": "Pests from Stereo Harmony vinyls glow blue outside of Jacob's Contests. Only enabled if Pest Highlighter is also enabled.", "skyblocker.config.farming.general.blocksPerSec": "Blocks/s: %s", "skyblocker.config.farming.general.coinsPerHour": "Coins/h: %s", From b241cf82031fd4158807811234e9e1c8ecd81779 Mon Sep 17 00:00:00 2001 From: LJNeon <23249107+LJNeon@users.noreply.github.com> Date: Thu, 12 Feb 2026 02:02:13 -0700 Subject: [PATCH 2/8] Fix issues & simplify code --- .../mixins/AbstractContainerScreenMixin.java | 6 --- .../skyblocker/skyblock/VacuumCache.java | 50 +++++++------------ .../entity/glow/adder/GardenGlowAdder.java | 2 +- .../skyblock/garden/GardenConstants.java | 20 +++++++- 4 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java index 4112be9bb21..e05f7bec704 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java @@ -27,7 +27,6 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.InventorySearch; import de.hysky.skyblocker.skyblock.PetCache; -import de.hysky.skyblocker.skyblock.VacuumCache; import de.hysky.skyblocker.skyblock.experiment.UltrasequencerSolver; import de.hysky.skyblocker.skyblock.garden.visitor.VisitorHelper; import de.hysky.skyblocker.skyblock.item.ItemPrice; @@ -391,11 +390,6 @@ protected AbstractContainerScreenMixin(Component title) { PetCache.handlePetEquip(slot, slotId); } - // Vacuum Vinyl Caching - if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && title.startsWith("Stereo Harmony")) { - VacuumCache.handleVinylSelect(slot, slotId); - } - if (currentSolver != null) { boolean disallowed = ContainerSolverManager.onSlotClick(slotId, stack, button); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java b/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java index 4a69d3aff72..63403f5e2a2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java @@ -2,8 +2,6 @@ import java.nio.file.Path; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.jspecify.annotations.Nullable; @@ -15,7 +13,6 @@ import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.data.ProfiledData; import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; -import net.minecraft.ChatFormatting; import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; @@ -23,7 +20,6 @@ public class VacuumCache { private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("vacuum_cache.json"); private static final ProfiledData CACHED_VINYL = new ProfiledData<>(FILE, Codec.STRING); - private static final Pattern VINYL_PATTERN = Pattern.compile("^When playing, (?[\\w\\s]+) Pests"); private VacuumCache() {} @@ -35,53 +31,41 @@ public static void init() { if (Utils.isOnSkyblock() && screen instanceof ContainerScreen genericContainerScreen) { if (genericContainerScreen.getTitle().getString().startsWith("Stereo Harmony")) { ScreenEvents.afterTick(screen).register(screen1 -> { + boolean noneSelected = true; + for (Slot slot : genericContainerScreen.getMenu().slots) { ItemStack stack = slot.getItem(); if (!stack.isEmpty() && ItemUtils.getLoreLineIf(stack, line -> line.equals("Click to stop playing!")) != null) { - parseVinyl(stack, false); + setVinyl(stack.getSkyblockId()); + noneSelected = false; break; } } + + if (noneSelected) setVinyl(null); }); } } }); } - public static void handleVinylSelect(Slot slot, int slotId) { - ItemStack stack = slot.getItem(); - - if (!stack.isEmpty()) parseVinyl(stack, true); - } - - private static void parseVinyl(ItemStack stack, boolean clicked) { - String profileId = Utils.getProfileId(); - - if (stack.getSkyblockId().startsWith("VINYL_") && !profileId.isEmpty()) { - @Nullable String vinyl = null; - - for (String line : stack.skyblocker$getLoreStrings()) { - String stringified = ChatFormatting.stripFormatting(line); - Matcher matcher = VINYL_PATTERN.matcher(stringified); + private static void setVinyl(@Nullable String skyblockId) { + if (Utils.getProfileId().isEmpty()) return; - if (matcher.matches()) { - vinyl = matcher.group("vinyl"); - - break; - } - } - - if (vinyl == null) return; - - if (clicked && getVinyl() != null && ItemUtils.getLoreLineIf(stack, line -> line.equals("Click to stop playing!")) != null) { + if (skyblockId == null) { + if (getVinyl() != null) { CACHED_VINYL.remove(); - } else { - CACHED_VINYL.put(vinyl); + CACHED_VINYL.save(); } + } else { + @Nullable String current = getVinyl(); - CACHED_VINYL.save(); + if (current == null || !current.equals(skyblockId)) { + CACHED_VINYL.put(skyblockId); + CACHED_VINYL.save(); + } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java index db452b74c7c..bd2e5c0389e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java @@ -112,7 +112,7 @@ public static boolean doesPestMatchCurrentVinyl(ArmorStand entity) { // Filter only pest head that matches by name return entity.hasItemInSlot(EquipmentSlot.HEAD) && GardenConstants.PEST_HEAD_BY_CROP - .get(GardenConstants.CROP_BY_PEST.get(vinyl)) + .get(GardenConstants.CROP_BY_VINYL.get(vinyl)) .contains(ItemUtils.getHeadTexture(entity.getItemBySlot(EquipmentSlot.HEAD))); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/GardenConstants.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/GardenConstants.java index 5a5f6e7b0bd..16e1045028f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/GardenConstants.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/GardenConstants.java @@ -1,12 +1,14 @@ package de.hysky.skyblocker.skyblock.garden; import static java.util.Map.entry; + import java.util.Map; -import net.minecraft.util.Util; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; + import de.hysky.skyblocker.skyblock.item.HeadTextures; +import net.minecraft.util.Util; public interface GardenConstants { Map CROP_BY_PEST = Map.ofEntries( @@ -42,4 +44,20 @@ public interface GardenConstants { map.put("Sunflower", HeadTextures.DRAGONFLY_PEST); map.put("Wild Rose", HeadTextures.PRAYING_MANTIS_PEST); }); + + Map CROP_BY_VINYL = Map.ofEntries( + entry("VINYL_PRETTY_FLY", "Wheat"), + entry("VINYL_BUZZIN_BEATS", "Sugar Cane"), + entry("VINYL_CRICKET_CHOIR", "Carrot"), + entry("VINYL_CICADA_SYMPHONY", "Potato"), + entry("VINYL_EARTHWORM_ENSEMBLE", "Melon Slice"), + entry("VINYL_RODENT_REVOLUTION", "Pumpkin"), + entry("VINYL_WINGS_OF_HARMONY", "Cocoa Beans"), + entry("VINYL_BEETLE", "Nether Wart"), + entry("VINYL_DYNAMITES", "Cactus"), + entry("VINYL_SLOW_AND_GROOVY", "Mushroom"), + entry("VINYL_FIREFLY", "Moonflower"), + entry("VINYL_IMAGINE_DRAGONFLIES", "Sunflower"), + entry("VINYL_PRAY_FOR_ME", "Wild Rose") + ); } From e007aec14081f0ebafe9a1ef980cf6dedf32d0f9 Mon Sep 17 00:00:00 2001 From: LJNeon <23249107+LJNeon@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:03:48 -0700 Subject: [PATCH 3/8] Clean up imports --- .../mixins/AbstractContainerScreenMixin.java | 34 +++++++++---------- .../skyblocker/skyblock/VacuumCache.java | 8 ++--- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java index e05f7bec704..b96d1a56ac3 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/AbstractContainerScreenMixin.java @@ -1,28 +1,10 @@ package de.hysky.skyblocker.mixins; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.regex.Matcher; - -import org.jspecify.annotations.Nullable; -import org.lwjgl.glfw.GLFW; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.datafixers.util.Either; - import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.InventorySearch; @@ -66,6 +48,22 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; +import org.jspecify.annotations.Nullable; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Matcher; @Mixin(AbstractContainerScreen.class) public abstract class AbstractContainerScreenMixin extends Screen { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java b/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java index 63403f5e2a2..b27da1a3d4d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java @@ -1,10 +1,5 @@ package de.hysky.skyblocker.skyblock; - -import java.nio.file.Path; - -import org.jspecify.annotations.Nullable; - import com.mojang.serialization.Codec; import de.hysky.skyblocker.SkyblockerMod; @@ -16,6 +11,9 @@ import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; +import org.jspecify.annotations.Nullable; + +import java.nio.file.Path; public class VacuumCache { private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("vacuum_cache.json"); From ffe7d818f11969e17252849d04afc98106990eb9 Mon Sep 17 00:00:00 2001 From: LJNeon <23249107+LJNeon@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:47:17 -0700 Subject: [PATCH 4/8] Use empty string instead of null to represent no vinyl selected --- .../hysky/skyblocker/skyblock/VacuumCache.java | 17 ++++++++--------- .../entity/glow/adder/GardenGlowAdder.java | 16 +++++++--------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java b/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java index b27da1a3d4d..6ea055c1593 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java @@ -11,7 +11,6 @@ import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import org.jspecify.annotations.Nullable; import java.nio.file.Path; @@ -42,32 +41,32 @@ public static void init() { } } - if (noneSelected) setVinyl(null); + if (noneSelected) setVinyl(""); }); } } }); } - private static void setVinyl(@Nullable String skyblockId) { + private static void setVinyl(String skyblockId) { if (Utils.getProfileId().isEmpty()) return; - if (skyblockId == null) { - if (getVinyl() != null) { + if (skyblockId.isEmpty()) { + if (!getVinyl().isEmpty()) { CACHED_VINYL.remove(); CACHED_VINYL.save(); } } else { - @Nullable String current = getVinyl(); + String current = getVinyl(); - if (current == null || !current.equals(skyblockId)) { + if (current.isEmpty() || !current.equals(skyblockId)) { CACHED_VINYL.put(skyblockId); CACHED_VINYL.save(); } } } - public static @Nullable String getVinyl() { - return CACHED_VINYL.get(); + public static String getVinyl() { + return CACHED_VINYL.containsKey() ? CACHED_VINYL.get() : ""; } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java index bd2e5c0389e..b7b5634f3c2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java @@ -3,24 +3,22 @@ import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; - +import net.minecraft.ChatFormatting; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.decoration.ArmorStand; import org.apache.commons.lang3.StringUtils; -import org.jspecify.annotations.Nullable; import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.skyblock.VacuumCache; import de.hysky.skyblocker.skyblock.entity.MobGlowAdder; import de.hysky.skyblocker.skyblock.garden.CurrentJacobCrop; import de.hysky.skyblocker.skyblock.garden.GardenConstants; import de.hysky.skyblocker.skyblock.item.HeadTextures; +import de.hysky.skyblocker.skyblock.VacuumCache; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.Scheduler; -import net.minecraft.ChatFormatting; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.decoration.ArmorStand; public class GardenGlowAdder extends MobGlowAdder { private static final GardenGlowAdder INSTANCE = new GardenGlowAdder(); @@ -103,10 +101,10 @@ public static boolean doesPestMatchCurrentVinyl(ArmorStand entity) { if (!SkyblockerConfigManager.get().farming.garden.vinylHighlighter) return false; - @Nullable String vinyl = VacuumCache.getVinyl(); + String vinyl = VacuumCache.getVinyl(); // Only applies outside of Jacob's Contests - if (!StringUtils.isEmpty(CurrentJacobCrop.CURRENT_CROP_CONTEST) || vinyl == null) { + if (!StringUtils.isEmpty(CurrentJacobCrop.CURRENT_CROP_CONTEST) || vinyl.isEmpty()) { return false; } From 8bfd765e4d72d19ae5772c8aa41f92485dcfaf69 Mon Sep 17 00:00:00 2001 From: LJNeon <23249107+LJNeon@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:49:51 -0700 Subject: [PATCH 5/8] Avoid re-ordering GardenConstants imports --- .../de/hysky/skyblocker/skyblock/garden/GardenConstants.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/GardenConstants.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/GardenConstants.java index 16e1045028f..28411bd1a7c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/GardenConstants.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/GardenConstants.java @@ -1,14 +1,12 @@ package de.hysky.skyblocker.skyblock.garden; import static java.util.Map.entry; - import java.util.Map; +import net.minecraft.util.Util; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; - import de.hysky.skyblocker.skyblock.item.HeadTextures; -import net.minecraft.util.Util; public interface GardenConstants { Map CROP_BY_PEST = Map.ofEntries( From 6ea807faf4b50a71a6d61cff05e563228aa978e8 Mon Sep 17 00:00:00 2001 From: LJNeon <23249107+LJNeon@users.noreply.github.com> Date: Tue, 17 Feb 2026 04:02:30 -0700 Subject: [PATCH 6/8] Change highlight color from aqua to dark aqua --- .../skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java index b7b5634f3c2..44d24022ceb 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java @@ -39,7 +39,7 @@ case ArmorStand as when isPestHead(as) -> ChatFormatting.GREEN.getColor() : // Pests from currently playing vinyl doesPestMatchCurrentVinyl(as) ? - ChatFormatting.AQUA.getColor() : + ChatFormatting.DARK_AQUA.getColor() : // Default color PEST_COLOUR; default -> NO_GLOW; From 518dad3fdb2e22ee0379f8de52ef8dbf1f87cff1 Mon Sep 17 00:00:00 2001 From: LJNeon <23249107+LJNeon@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:51:07 -0700 Subject: [PATCH 7/8] Move to garden package & minor improvements --- .../skyblock/entity/glow/adder/GardenGlowAdder.java | 6 +++--- .../skyblocker/skyblock/{ => garden}/VacuumCache.java | 11 ++++------- 2 files changed, 7 insertions(+), 10 deletions(-) rename src/main/java/de/hysky/skyblocker/skyblock/{ => garden}/VacuumCache.java (89%) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java index 44d24022ceb..0b79a3a7fd2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/glow/adder/GardenGlowAdder.java @@ -14,8 +14,8 @@ import de.hysky.skyblocker.skyblock.entity.MobGlowAdder; import de.hysky.skyblocker.skyblock.garden.CurrentJacobCrop; import de.hysky.skyblocker.skyblock.garden.GardenConstants; +import de.hysky.skyblocker.skyblock.garden.VacuumCache; import de.hysky.skyblocker.skyblock.item.HeadTextures; -import de.hysky.skyblocker.skyblock.VacuumCache; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.Scheduler; @@ -89,7 +89,7 @@ public static boolean doesPestMatchCurrentContest(ArmorStand entity) { } // Filter only pest head that matches by crop - return entity.hasItemInSlot(EquipmentSlot.HEAD) && GardenConstants.PEST_HEAD_BY_CROP + return GardenConstants.PEST_HEAD_BY_CROP .get(CurrentJacobCrop.CURRENT_CROP_CONTEST) .contains(ItemUtils.getHeadTexture(entity.getItemBySlot(EquipmentSlot.HEAD))); } @@ -109,7 +109,7 @@ public static boolean doesPestMatchCurrentVinyl(ArmorStand entity) { } // Filter only pest head that matches by name - return entity.hasItemInSlot(EquipmentSlot.HEAD) && GardenConstants.PEST_HEAD_BY_CROP + return GardenConstants.PEST_HEAD_BY_CROP .get(GardenConstants.CROP_BY_VINYL.get(vinyl)) .contains(ItemUtils.getHeadTexture(entity.getItemBySlot(EquipmentSlot.HEAD))); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VacuumCache.java similarity index 89% rename from src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java rename to src/main/java/de/hysky/skyblocker/skyblock/garden/VacuumCache.java index 6ea055c1593..733d0143f15 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/VacuumCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VacuumCache.java @@ -1,4 +1,4 @@ -package de.hysky.skyblocker.skyblock; +package de.hysky.skyblocker.skyblock.garden; import com.mojang.serialization.Codec; @@ -28,20 +28,17 @@ public static void init() { if (Utils.isOnSkyblock() && screen instanceof ContainerScreen genericContainerScreen) { if (genericContainerScreen.getTitle().getString().startsWith("Stereo Harmony")) { ScreenEvents.afterTick(screen).register(screen1 -> { - boolean noneSelected = true; - for (Slot slot : genericContainerScreen.getMenu().slots) { ItemStack stack = slot.getItem(); if (!stack.isEmpty() && ItemUtils.getLoreLineIf(stack, line -> line.equals("Click to stop playing!")) != null) { setVinyl(stack.getSkyblockId()); - noneSelected = false; - break; + return; } } - if (noneSelected) setVinyl(""); + setVinyl(""); }); } } @@ -59,7 +56,7 @@ private static void setVinyl(String skyblockId) { } else { String current = getVinyl(); - if (current.isEmpty() || !current.equals(skyblockId)) { + if (!current.equals(skyblockId)) { CACHED_VINYL.put(skyblockId); CACHED_VINYL.save(); } From dc9566efcb1c5c7c4467602dffabad78e5dfdb3e Mon Sep 17 00:00:00 2001 From: LJ <23249107+LJNeon@users.noreply.github.com> Date: Mon, 23 Feb 2026 18:54:27 -0700 Subject: [PATCH 8/8] Fix merge issue Co-authored-by: Alex <8379108+Alex33856@users.noreply.github.com> --- src/main/resources/assets/skyblocker/lang/en_us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index 5ec97cce4d8..54e266dd7f7 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -455,7 +455,7 @@ "skyblocker.config.farming.garden.lockMouseGround": "Only lock camera when on the ground", "skyblocker.config.farming.garden.lockMouseTool": "Lock camera when holding a farming tool", "skyblocker.config.farming.garden.pestHighlighter": "Pest Highlighter", - "skyblocker.config.farming.garden.pestHighlighter.@Tooltip": "Make's all pest's on your island glow so you can see them easier :D", + "skyblocker.config.farming.garden.pestHighlighter.@Tooltip": "Makes all pests on your island glow so you can see them easier :D", "skyblocker.config.farming.garden.vinylHighlighter": "Stereo Harmony Vinyl Highlighter", "skyblocker.config.farming.garden.vinylHighlighter.@Tooltip": "Pests from Stereo Harmony vinyls glow blue outside of Jacob's Contests. Only enabled if Pest Highlighter is also enabled.",