diff options
Diffstat (limited to 'src/main/java')
15 files changed, 244 insertions, 111 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index dca41bd1..36ef5a4f 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -18,6 +18,7 @@ import de.hysky.skyblocker.skyblock.dwarven.CrystalsLocationsManager; import de.hysky.skyblocker.skyblock.dwarven.DwarvenHud; import de.hysky.skyblocker.skyblock.end.BeaconHighlighter; import de.hysky.skyblocker.skyblock.end.TheEnd; +import de.hysky.skyblocker.skyblock.garden.VisitorHelper; import de.hysky.skyblocker.skyblock.item.*; import de.hysky.skyblocker.skyblock.item.tooltip.BackpackPreview; import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip; @@ -139,6 +140,7 @@ public class SkyblockerMod implements ClientModInitializer { ItemProtection.init(); CreeperBeams.init(); Boulder.init(); + VisitorHelper.init(); ItemRarityBackgrounds.init(); MuseumItemCache.init(); SecretsTracker.init(); diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java index 713a9fbd..b4e520e2 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java @@ -178,9 +178,6 @@ public class SkyblockerConfig { public boolean dungeonQuality = true; @SerialEntry - public boolean visitorHelper = true; - - @SerialEntry public TabHudConf tabHud = new TabHudConf(); @SerialEntry @@ -468,10 +465,10 @@ public class SkyblockerConfig { public static class FlameOverlay { @SerialEntry - public float flameHeight = 0f; + public int flameHeight = 100; @SerialEntry - public float flameOpacity = 0f; + public int flameOpacity = 100; } public static class SearchOverlay { @@ -1094,6 +1091,9 @@ public class SkyblockerConfig { public static class Garden { @SerialEntry public boolean dicerTitlePrevent = true; + + @SerialEntry + public boolean visitorHelper = true; } public static class Slayer { 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 8a7d832c..afd688d8 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -86,13 +86,6 @@ public class GeneralCategory { newValue -> config.general.dungeonQuality = newValue) .controller(ConfigUtils::createBooleanController) .build()) - .option(Option.<Boolean>createBuilder() - .name(Text.translatable("text.autoconfig.skyblocker.option.general.visitorHelper")) - .binding(defaults.general.visitorHelper, - () -> config.general.visitorHelper, - newValue -> config.general.visitorHelper = newValue) - .controller(ConfigUtils::createBooleanController) - .build()) //Tab Hud .group(OptionGroup.createBuilder() @@ -642,19 +635,21 @@ public class GeneralCategory { .group(OptionGroup.createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.general.flameOverlay")) .collapsed(true) - .option(Option.<Float>createBuilder() + .option(Option.<Integer>createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.general.flameOverlay.flameHeight")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.general.flameOverlay.flameHeight.@Tooltip"))) .binding(defaults.general.flameOverlay.flameHeight, () -> config.general.flameOverlay.flameHeight, newValue -> config.general.flameOverlay.flameHeight = newValue) - .controller(opt -> FloatSliderControllerBuilder.create(opt).range(0.0f, 0.5f).step(0.01f)) + .controller(opt -> IntegerSliderControllerBuilder.create(opt).range(0, 100).step(1)) .build()) - .option(Option.<Float>createBuilder() + .option(Option.<Integer>createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.general.flameOverlay.flameOpacity")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.general.flameOverlay.flameOpacity.@Tooltip"))) .binding(defaults.general.flameOverlay.flameOpacity, () -> config.general.flameOverlay.flameOpacity, newValue -> config.general.flameOverlay.flameOpacity = newValue) - .controller(opt -> FloatSliderControllerBuilder.create(opt).range(0.0f, 0.8f).step(0.1f)) + .controller(opt -> IntegerSliderControllerBuilder.create(opt).range(0, 100).step(1)) .build()) .build()) diff --git a/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java index 75c83a9b..d97513f8 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java @@ -153,6 +153,13 @@ public class LocationsCategory { newValue -> config.locations.garden.dicerTitlePrevent = newValue) .controller(ConfigUtils::createBooleanController) .build()) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.general.visitorHelper")) + .binding(defaults.locations.garden.visitorHelper, + () -> config.locations.garden.visitorHelper, + newValue -> config.locations.garden.visitorHelper = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) .build()) .build(); } diff --git a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java index 8a1af570..7d2f849e 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java @@ -1,6 +1,7 @@ package de.hysky.skyblocker.mixin; import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.systems.RenderSystem; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.experiment.ChronomatronSolver; @@ -16,11 +17,9 @@ import de.hysky.skyblocker.skyblock.item.tooltip.CompactorDeletorPreview; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.gui.ContainerSolver; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.item.TooltipContext; import net.minecraft.inventory.SimpleInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -29,6 +28,7 @@ import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; import net.minecraft.text.Text; +import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; @@ -42,6 +42,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Map; +import java.util.Set; import java.util.regex.Matcher; @Mixin(HandledScreen.class) @@ -52,6 +53,34 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen @Unique private static final int OUT_OF_BOUNDS_SLOT = -999; + @Unique + private static final Identifier ITEM_PROTECTION = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/item_protection.png"); + + @Unique + private static final Set<String> FILLER_ITEMS = Set.of( + " ", // Empty menu item + "Locked Page", + "Quick Crafting Slot", + "Locked Backpack Slot 2", //Regular expressions won't be utilized here since the search by contains is based on plain text rather than regex syntax + "Locked Backpack Slot 3", + "Locked Backpack Slot 4", + "Locked Backpack Slot 5", + "Locked Backpack Slot 6", + "Locked Backpack Slot 7", + "Locked Backpack Slot 8", + "Locked Backpack Slot 9", + "Locked Backpack Slot 10", + "Locked Backpack Slot 11", + "Locked Backpack Slot 12", + "Locked Backpack Slot 13", + "Locked Backpack Slot 14", + "Locked Backpack Slot 15", + "Locked Backpack Slot 16", + "Locked Backpack Slot 17", + "Locked Backpack Slot 18", + "Preparing" + ); + @Shadow @Nullable protected Slot focusedSlot; @@ -66,22 +95,21 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen @Inject(at = @At("HEAD"), method = "keyPressed") public void skyblocker$keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable<Boolean> cir) { - if (this.client != null && this.focusedSlot != null && keyCode != 256 && !this.client.options.inventoryKey.matchesKey(keyCode, scanCode) && WikiLookup.wikiLookup.matchesKey(keyCode, scanCode)) { - WikiLookup.openWiki(this.focusedSlot, client.player); + if (this.client != null && this.focusedSlot != null && keyCode != 256) { + //wiki lookup + if (!this.client.options.inventoryKey.matchesKey(keyCode, scanCode) && WikiLookup.wikiLookup.matchesKey(keyCode, scanCode)) { + WikiLookup.openWiki(this.focusedSlot, client.player); + } + //item protection + if (!this.client.options.inventoryKey.matchesKey(keyCode, scanCode) && ItemProtection.itemProtection.matchesKey(keyCode, scanCode)) { + ItemProtection.handleKeyPressed(this.focusedSlot.getStack()); + } } } - @Inject(at = @At("RETURN"), method = "render") - public void skyblocker$renderScreen(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - if (!Utils.isOnSkyblock()) return; - - if (SkyblockerConfigManager.get().general.visitorHelper && (Utils.getLocationRaw().equals("garden") && !getTitle().getString().contains("Logbook") || getTitle().getString().startsWith("Bazaar"))) - VisitorHelper.renderScreen(this.getTitle().getString(), context, textRenderer, handler, mouseX, mouseY); - } - @Inject(at = @At("HEAD"), method = "mouseClicked") public void skyblocker$mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> cir) { - if (SkyblockerConfigManager.get().general.visitorHelper && (Utils.getLocationRaw().equals("garden") && !getTitle().getString().contains("Logbook") || getTitle().getString().startsWith("Bazaar"))) + if (SkyblockerConfigManager.get().locations.garden.visitorHelper && (Utils.getLocationRaw().equals("garden") && !getTitle().getString().contains("Logbook") || getTitle().getString().startsWith("Bazaar"))) VisitorHelper.onMouseClicked(mouseX, mouseY, button, this.textRenderer); } @@ -121,6 +149,9 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen return skyblocker$experimentSolvers$getStack(slot, stack); } + /** + * Redirects getStack calls to account for different stacks in experiment solvers. + */ @Unique private ItemStack skyblocker$experimentSolvers$getStack(Slot slot, @NotNull ItemStack stack) { ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver(); @@ -131,81 +162,84 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen return stack; } - @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;clickSlot(IIILnet/minecraft/screen/slot/SlotActionType;Lnet/minecraft/entity/player/PlayerEntity;)V")) - private void skyblocker$experimentSolvers$onSlotClick(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { - if (slot != null) { - ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver(); - if (currentSolver instanceof ExperimentSolver experimentSolver && experimentSolver.getState() == ExperimentSolver.State.SHOW && slot.inventory instanceof SimpleInventory) { - if (experimentSolver instanceof ChronomatronSolver chronomatronSolver) { - Item item = chronomatronSolver.getChronomatronSlots().get(chronomatronSolver.getChronomatronCurrentOrdinal()); - if ((slot.getStack().isOf(item) || ChronomatronSolver.TERRACOTTA_TO_GLASS.get(slot.getStack().getItem()) == item) && chronomatronSolver.incrementChronomatronCurrentOrdinal() >= chronomatronSolver.getChronomatronSlots().size()) { - chronomatronSolver.setState(ExperimentSolver.State.END); - } - } else if (experimentSolver instanceof SuperpairsSolver superpairsSolver) { - superpairsSolver.setSuperpairsPrevClickedSlot(slot.getIndex()); - superpairsSolver.setSuperpairsCurrentSlot(ItemStack.EMPTY); - } else if (experimentSolver instanceof UltrasequencerSolver ultrasequencerSolver && slot.getIndex() == ultrasequencerSolver.getUltrasequencerNextSlot()) { - int count = ultrasequencerSolver.getSlots().get(ultrasequencerSolver.getUltrasequencerNextSlot()).getCount() + 1; - ultrasequencerSolver.getSlots().entrySet().stream().filter(entry -> entry.getValue().getCount() == count).findAny().map(Map.Entry::getKey).ifPresentOrElse(ultrasequencerSolver::setUltrasequencerNextSlot, () -> ultrasequencerSolver.setState(ExperimentSolver.State.END)); - } - } - } - } - /** * The naming of this method in yarn is half true, its mostly to handle slot/item interactions (which are mouse or keyboard clicks) * For example, using the drop key bind while hovering over an item will invoke this method to drop the players item */ - @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true) - private void skyblocker$onSlotInteract(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { - if (Utils.isOnSkyblock()) { - // When you try and drop the item by picking it up then clicking outside of the screen - if (slotId == OUT_OF_BOUNDS_SLOT) { - ItemStack cursorStack = this.handler.getCursorStack(); - - if (ItemProtection.isItemProtected(cursorStack)) ci.cancel(); - } - - if (slot != null) { - // When you click your drop key while hovering over an item - if (actionType == SlotActionType.THROW) { - ItemStack stack = slot.getStack(); + @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;clickSlot(IIILnet/minecraft/screen/slot/SlotActionType;Lnet/minecraft/entity/player/PlayerEntity;)V"), cancellable = true) + private void skyblocker$onSlotClick(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { + if (!Utils.isOnSkyblock()) return; - if (ItemProtection.isItemProtected(stack)) ci.cancel(); - } + // Item Protection + // When you try and drop the item by picking it up then clicking outside the screen + if (slotId == OUT_OF_BOUNDS_SLOT && ItemProtection.isItemProtected(this.handler.getCursorStack())) { + ci.cancel(); + return; + } - //Prevent salvaging - if (this.getTitle().getString().equals("Salvage Items")) { - ItemStack stack = slot.getStack(); + if (slot == null) return; + String title = getTitle().getString(); + ItemStack stack = skyblocker$experimentSolvers$getStack(slot, slot.getStack()); + ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver(); - if (ItemProtection.isItemProtected(stack)) ci.cancel(); + // Prevent clicks on filler items + if (SkyblockerConfigManager.get().general.hideEmptyTooltips && FILLER_ITEMS.contains(stack.getName().getString()) && + // Allow clicks in Ultrasequencer and Superpairs + (!UltrasequencerSolver.INSTANCE.getName().matcher(title).matches() || SkyblockerConfigManager.get().general.experiments.enableUltrasequencerSolver)) { + ci.cancel(); + return; + } + // Item Protection + // When you click your drop key while hovering over an item + if (actionType == SlotActionType.THROW && ItemProtection.isItemProtected(stack)) { + ci.cancel(); + return; + } + // Prevent salvaging + if (title.equals("Salvage Items") && ItemProtection.isItemProtected(stack)) { + ci.cancel(); + return; + } + if (this.handler instanceof GenericContainerScreenHandler genericContainerScreenHandler && genericContainerScreenHandler.getRows() == 6) { + VisitorHelper.onSlotClick(slot, slotId, title); + + // Prevent selling to NPC shops + ItemStack sellStack = this.handler.slots.get(49).getStack(); + if (sellStack.getName().getString().equals("Sell Item") || ItemUtils.getNbtTooltip(sellStack, text -> text.contains("buyback")) != null) { + if (slotId != 49 && ItemProtection.isItemProtected(stack)) { + ci.cancel(); + return; } + } + } - - if (this.client != null && this.handler instanceof GenericContainerScreenHandler genericContainerScreenHandler && genericContainerScreenHandler.getRows() == 6) { - VisitorHelper.onSlotClick(slot, slotId, this.getTitle().getString()); - - //Prevent selling to NPC shops - ItemStack sellItem = this.handler.slots.get(49).getStack(); - - if (sellItem.getName().getString().equals("Sell Item") || skyblocker$doesLoreContain(sellItem, this.client, "buyback")) { - ItemStack stack = slot.getStack(); - - if (ItemProtection.isItemProtected(stack)) ci.cancel(); - } + // Experiment Solvers + if (currentSolver instanceof ExperimentSolver experimentSolver && experimentSolver.getState() == ExperimentSolver.State.SHOW && slot.inventory instanceof SimpleInventory) { + if (experimentSolver instanceof ChronomatronSolver chronomatronSolver) { + Item item = chronomatronSolver.getChronomatronSlots().get(chronomatronSolver.getChronomatronCurrentOrdinal()); + if ((stack.isOf(item) || ChronomatronSolver.TERRACOTTA_TO_GLASS.get(stack.getItem()) == item) && chronomatronSolver.incrementChronomatronCurrentOrdinal() >= chronomatronSolver.getChronomatronSlots().size()) { + chronomatronSolver.setState(ExperimentSolver.State.END); } + } else if (experimentSolver instanceof SuperpairsSolver superpairsSolver) { + superpairsSolver.setSuperpairsPrevClickedSlot(slot.getIndex()); + superpairsSolver.setSuperpairsCurrentSlot(ItemStack.EMPTY); + } else if (experimentSolver instanceof UltrasequencerSolver ultrasequencerSolver && slot.getIndex() == ultrasequencerSolver.getUltrasequencerNextSlot()) { + int count = ultrasequencerSolver.getSlots().get(ultrasequencerSolver.getUltrasequencerNextSlot()).getCount() + 1; + ultrasequencerSolver.getSlots().entrySet().stream().filter(entry -> entry.getValue().getCount() == count).findAny().map(Map.Entry::getKey).ifPresentOrElse(ultrasequencerSolver::setUltrasequencerNextSlot, () -> ultrasequencerSolver.setState(ExperimentSolver.State.END)); } + return; } } - //TODO make this a util method somewhere else, eventually - private static boolean skyblocker$doesLoreContain(ItemStack stack, MinecraftClient client, String searchString) { - return stack.getTooltip(client.player, TooltipContext.BASIC).stream().map(Text::getString).anyMatch(line -> line.contains(searchString)); - } - @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V")) private void skyblocker$drawItemRarityBackground(DrawContext context, Slot slot, CallbackInfo ci) { if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) ItemRarityBackgrounds.tryDraw(slot.getStack(), context, slot.x, slot.y); + // Item protection + if (ItemProtection.isItemProtected(slot.getStack())) { + RenderSystem.enableBlend(); + context.drawTexture(ITEM_PROTECTION, slot.x, slot.y, 0, 0, 16, 16, 16, 16); + RenderSystem.disableBlend(); + } } } diff --git a/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java b/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java index 88be60cd..5e3daf3c 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java @@ -3,6 +3,7 @@ package de.hysky.skyblocker.mixin; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.systems.RenderSystem; +import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.FancyStatusBars; import de.hysky.skyblocker.skyblock.dungeon.DungeonMap; @@ -10,6 +11,7 @@ import de.hysky.skyblocker.skyblock.dungeon.DungeonScore; import de.hysky.skyblocker.skyblock.dungeon.DungeonScoreHUD; 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.utils.Utils; import net.fabricmc.api.EnvType; @@ -38,6 +40,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; public abstract class InGameHudMixin { @Unique private static final Supplier<Identifier> SLOT_LOCK_ICON = () -> SkyblockerConfigManager.get().general.itemProtection.slotLockStyle.tex; + + @Unique + private static final Identifier ITEM_PROTECTION = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/item_protection.png"); @Unique private static final Pattern DICER_TITLE_BLACKLIST = Pattern.compile(".+? DROP!"); @@ -56,12 +61,19 @@ public abstract class InGameHudMixin { @Inject(method = "renderHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHotbarItem(Lnet/minecraft/client/gui/DrawContext;IIFLnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;I)V", ordinal = 0)) public void skyblocker$renderHotbarItemLockOrRarityBg(float tickDelta, DrawContext context, CallbackInfo ci, @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().main.get(index), context, x, y); if (HotbarSlotLock.isLocked(index)) { RenderSystem.enableBlend(); context.drawTexture(SLOT_LOCK_ICON.get(), x, y, 0, 0, 16, 16, 16, 16); RenderSystem.disableBlend(); } + //item protection + if (ItemProtection.isItemProtected(player.getInventory().main.get(index))){ + RenderSystem.enableBlend(); + context.drawTexture(ITEM_PROTECTION, x, y, 0, 0, 16, 16, 16, 16); + RenderSystem.disableBlend(); + } } } diff --git a/src/main/java/de/hysky/skyblocker/mixin/InGameOverlayRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixin/InGameOverlayRendererMixin.java index b957603a..4775ce2d 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/InGameOverlayRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/InGameOverlayRendererMixin.java @@ -11,12 +11,12 @@ public class InGameOverlayRendererMixin { @ModifyArg(method = "renderFireOverlay", index = 2, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/BufferBuilder;vertex(Lorg/joml/Matrix4f;FFF)Lnet/minecraft/client/render/VertexConsumer;")) private static float configureFlameHeight(float y) { - return y - SkyblockerConfigManager.get().general.flameOverlay.flameHeight; + return y - (0.5f - ((float) SkyblockerConfigManager.get().general.flameOverlay.flameHeight / 200.0f)); } @ModifyArg(method = "renderFireOverlay", index = 3, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/VertexConsumer;color(FFFF)Lnet/minecraft/client/render/VertexConsumer;")) private static float configureFlameOpacity(float opacity) { - return opacity - SkyblockerConfigManager.get().general.flameOverlay.flameOpacity; + return opacity - (0.8f - ((float) SkyblockerConfigManager.get().general.flameOverlay.flameOpacity / 125.0f)); } } diff --git a/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java b/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java index cf8aab78..dd671b2e 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java @@ -1,6 +1,7 @@ package de.hysky.skyblocker.mixin; import de.hysky.skyblocker.skyblock.item.HotbarSlotLock; +import de.hysky.skyblocker.skyblock.item.ItemProtection; import de.hysky.skyblocker.utils.JoinWorldPlaceholderScreen; import de.hysky.skyblocker.utils.ReconfiguringPlaceholderScreen; import de.hysky.skyblocker.utils.Utils; @@ -34,6 +35,7 @@ public abstract class MinecraftClientMixin { public void skyblocker$handleInputEvents(CallbackInfo ci) { if (Utils.isOnSkyblock()) { HotbarSlotLock.handleInputEvents(player); + ItemProtection.handleHotbarKeyPressed(player); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java b/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java index 746235b7..4e87b237 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/experiment/UltrasequencerSolver.java @@ -12,9 +12,10 @@ import java.util.List; import java.util.Map; public class UltrasequencerSolver extends ExperimentSolver { + public static final UltrasequencerSolver INSTANCE = new UltrasequencerSolver(); private int ultrasequencerNextSlot; - public UltrasequencerSolver() { + private UltrasequencerSolver() { super("^Ultrasequencer \\(\\w+\\)$"); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java index 3c049f69..4fd9eeb3 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java @@ -1,13 +1,17 @@ package de.hysky.skyblocker.skyblock.garden; +import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.utils.NEURepoManager; +import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.MessageScheduler; import io.github.moulberry.repo.data.NEUItem; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; @@ -32,11 +36,20 @@ public class VisitorHelper { private static final Map<String, ItemStack> itemCache = new HashMap<>(); private static final int TEXT_START_X = 4; private static final int TEXT_START_Y = 4; + private static final int TEXT_INDENT = 8; private static final int LINE_SPACING = 3; + public static void init() { + ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + String title = screen.getTitle().getString(); + if (SkyblockerConfigManager.get().locations.garden.visitorHelper && screen instanceof HandledScreen<?> handledScreen && (Utils.getLocationRaw().equals("garden") && !title.contains("Logbook") || title.startsWith("Bazaar"))) { + ScreenEvents.afterRender(screen).register((screen_, context, mouseX, mouseY, delta) -> renderScreen(title, context, client.textRenderer, handledScreen.getScreenHandler(), mouseX, mouseY)); + } + }); + } + public static void renderScreen(String title, DrawContext context, TextRenderer textRenderer, ScreenHandler handler, int mouseX, int mouseY) { - if (handler.getCursorStack() == ItemStack.EMPTY) - processVisitorItem(title, handler); + if (handler.getCursorStack() == ItemStack.EMPTY) processVisitorItem(title, handler); drawScreenItems(context, textRenderer, mouseX, mouseY); } @@ -51,9 +64,9 @@ public class VisitorHelper { for (Object2IntMap.Entry<String> itemEntry : visitorEntry.getValue().object2IntEntrySet()) { String itemText = itemEntry.getKey(); - textWidth = textRenderer.getWidth(itemText); + textWidth = textRenderer.getWidth(itemText + " x" + itemEntry.getIntValue()); - if (isMouseOverText(mouseX, mouseY, TEXT_START_X, yPosition, textWidth, textHeight)) { + if (isMouseOverText(mouseX, mouseY, TEXT_START_X + TEXT_INDENT, yPosition, textWidth, textHeight)) { MessageScheduler.INSTANCE.sendMessageAfterCooldown("/bz " + itemText); return; } @@ -107,6 +120,8 @@ public class VisitorHelper { } private static void drawScreenItems(DrawContext context, TextRenderer textRenderer, int mouseX, int mouseY) { + context.getMatrices().push(); + context.getMatrices().translate(0, 0, 200); int index = 0; for (Map.Entry<String, Object2IntMap<String>> visitorEntry : itemMap.entrySet()) { String visitorName = visitorEntry.getKey(); @@ -117,6 +132,7 @@ public class VisitorHelper { index = drawItemEntryWithHover(context, textRenderer, itemEntry, index, mouseX, mouseY); } } + context.getMatrices().pop(); } private static int drawItemEntryWithHover(DrawContext context, TextRenderer textRenderer, Map.Entry<String, Integer> itemEntry, int index, int mouseX, int mouseY) { @@ -145,15 +161,19 @@ public class VisitorHelper { private static void drawItemEntryWithHover(DrawContext context, TextRenderer textRenderer, ItemStack stack, int amount, int index, int mouseX, int mousseY) { Text text = Serialization.fromJson(stack.getSubNbt("display").getString("Name")).append(" x" + amount); - drawTextWithOptionalUnderline(context, textRenderer, text, TEXT_START_X + 8, TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), mouseX, mousseY); - context.drawItem(stack, TEXT_START_X + 10 + textRenderer.getWidth(text), TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)) - textRenderer.fontHeight + 5); + drawTextWithOptionalUnderline(context, textRenderer, text, TEXT_START_X + TEXT_INDENT, TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)), mouseX, mousseY); + // drawItem adds 150 to the z, which puts our z at 350, above the item in the slot (250) and their text (300) and below the cursor stack (382) and their text (432) + context.drawItem(stack, TEXT_START_X + TEXT_INDENT + 2 + textRenderer.getWidth(text), TEXT_START_Y + (index * (LINE_SPACING + textRenderer.fontHeight)) - textRenderer.fontHeight + 5); } private static void drawTextWithOptionalUnderline(DrawContext context, TextRenderer textRenderer, Text text, int x, int y, int mouseX, int mouseY) { + context.getMatrices().push(); + context.getMatrices().translate(0, 0, 150); // This also puts our z at 350 context.drawText(textRenderer, text, x, y, -1, true); if (isMouseOverText(mouseX, mouseY, x, y, textRenderer.getWidth(text), textRenderer.fontHeight)) { context.drawHorizontalLine(x, x + textRenderer.getWidth(text), y + textRenderer.fontHeight, -1); } + context.getMatrices().pop(); } private static boolean isMouseOverText(double mouseX, double mouseY, int x, int y, int width, int height) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java index 2d929c28..7e04652c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java @@ -10,13 +10,25 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; 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.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.option.KeyBinding; import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; public class ItemProtection { + public static KeyBinding itemProtection; public static void init() { + itemProtection = KeyBindingHelper.registerKeyBinding(new KeyBinding( + "key.itemProtection", + GLFW.GLFW_KEY_V, + "key.categories.skyblocker" + )); ClientCommandRegistrationCallback.EVENT.register(ItemProtection::registerCommand); } @@ -61,4 +73,46 @@ public class ItemProtection { return Command.SINGLE_SUCCESS; } + + public static void handleKeyPressed(ItemStack heldItem) { + PlayerEntity playerEntity = MinecraftClient.getInstance().player; + if (playerEntity == null){ + return; + } + if (!Utils.isOnSkyblock()) { + playerEntity.sendMessage(Constants.PREFIX.get().append(Text.translatable("skyblocker.itemProtection.unableToProtect"))); + return; + } + + if (heldItem.isEmpty()) { + playerEntity.sendMessage(Constants.PREFIX.get().append(Text.translatable("skyblocker.itemProtection.noItemUuid"))); + return; + } + + String itemUuid = ItemUtils.getItemUuid(heldItem); + if (!itemUuid.isEmpty()) { + ObjectOpenHashSet<String> protectedItems = SkyblockerConfigManager.get().general.protectedItems; + + if (!protectedItems.contains(itemUuid)) { + protectedItems.add(itemUuid); + SkyblockerConfigManager.save(); + + playerEntity.sendMessage(Constants.PREFIX.get().append(Text.translatable("skyblocker.itemProtection.added", heldItem.getName()))); + } else { + protectedItems.remove(itemUuid); + SkyblockerConfigManager.save(); + + playerEntity.sendMessage(Constants.PREFIX.get().append(Text.translatable("skyblocker.itemProtection.removed", heldItem.getName()))); + } + } else { + playerEntity.sendMessage(Constants.PREFIX.get().append(Text.translatable("skyblocker.itemProtection.noItemUuid"))); + } + } + + public static void handleHotbarKeyPressed(ClientPlayerEntity player) { + while (itemProtection.wasPressed()) { + ItemStack heldItem = player.getMainHandStack(); + handleKeyPressed(heldItem); + } + } } 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 d5be7eee..fbef1bcb 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 @@ -51,7 +51,7 @@ public class ItemTooltip { boolean bazaarOpened = lines.stream().anyMatch(each -> each.getString().contains("Buy price:") || each.getString().contains("Sell price:")); if (TooltipInfoType.NPC.isTooltipEnabledAndHasOrNullWarning(internalID)) { - lines.add(Text.literal(String.format("%-21s", "NPC Price:")) + lines.add(Text.literal(String.format("%-21s", "NPC Sell Price:")) .formatted(Formatting.YELLOW) .append(getCoinsMessage(TooltipInfoType.NPC.getData().get(internalID).getAsDouble(), count))); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/DungeonSecretWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/DungeonSecretWidget.java index 6f40f5a8..309ba9ca 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/DungeonSecretWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/DungeonSecretWidget.java @@ -1,16 +1,19 @@ package de.hysky.skyblocker.skyblock.tabhud.widget; import de.hysky.skyblocker.skyblock.tabhud.util.Ico; +import de.hysky.skyblocker.skyblock.tabhud.util.PlayerListMgr; import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import java.util.regex.Pattern; + // this widget shows info about the secrets of the dungeon public class DungeonSecretWidget extends Widget { - private static final MutableText TITLE = Text.literal("Discoveries").formatted(Formatting.DARK_PURPLE, - Formatting.BOLD); + private static final MutableText TITLE = Text.literal("Discoveries").formatted(Formatting.DARK_PURPLE, Formatting.BOLD); + private static final Pattern DISCOVERIES = Pattern.compile("Discoveries: (\\d+)"); public DungeonSecretWidget() { super(TITLE, Formatting.DARK_PURPLE.getColorValue()); @@ -18,9 +21,12 @@ public class DungeonSecretWidget extends Widget { @Override public void updateContent() { - this.addSimpleIcoText(Ico.CHEST, "Secrets:", Formatting.YELLOW, 31); - this.addSimpleIcoText(Ico.SKULL, "Crypts:", Formatting.YELLOW, 32); - + if (PlayerListMgr.regexAt(31, DISCOVERIES) != null) { + this.addSimpleIcoText(Ico.CHEST, "Secrets:", Formatting.YELLOW, 32); + this.addSimpleIcoText(Ico.SKULL, "Crypts:", Formatting.YELLOW, 33); + } else { + this.addSimpleIcoText(Ico.CHEST, "Secrets:", Formatting.YELLOW, 31); + this.addSimpleIcoText(Ico.SKULL, "Crypts:", Formatting.YELLOW, 32); + } } - } diff --git a/src/main/java/de/hysky/skyblocker/utils/Http.java b/src/main/java/de/hysky/skyblocker/utils/Http.java index 17079d15..58deced2 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Http.java +++ b/src/main/java/de/hysky/skyblocker/utils/Http.java @@ -53,7 +53,7 @@ public class Http { String body = new String(decodedInputStream.readAllBytes()); HttpHeaders headers = response.headers(); - return new ApiResponse(body, response.statusCode(), getCacheStatus(headers), getAge(headers)); + return new ApiResponse(body, response.statusCode(), getCacheStatuses(headers), getAge(headers)); } public static HttpHeaders sendHeadRequest(String url) throws IOException, InterruptedException { @@ -115,12 +115,12 @@ public class Http { } /** - * Returns the cache status of the resource + * Returns the cache statuses of the resource. All possible cache status values conform to Cloudflare's. * - * @see <a href="https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#cloudflare-cache-responses">Cloudflare Cache Docs</a> + * @see <a href="https://developers.cloudflare.com/cache/concepts/cache-responses/">Cloudflare Cache Docs</a> */ - private static String getCacheStatus(HttpHeaders headers) { - return headers.firstValue("CF-Cache-Status").orElse("UNKNOWN"); + private static String[] getCacheStatuses(HttpHeaders headers) { + return new String[] { headers.firstValue("CF-Cache-Status").orElse("UNKNOWN"), headers.firstValue("Local-Cache-Status").orElse("UNKNOWN") }; } private static int getAge(HttpHeaders headers) { @@ -128,7 +128,7 @@ public class Http { } //TODO If ever needed, we could just replace cache status with the response headers and go from there - public record ApiResponse(String content, int statusCode, String cacheStatus, int age) implements AutoCloseable { + public record ApiResponse(String content, int statusCode, String[] cacheStatuses, int age) implements AutoCloseable { public boolean ok() { return statusCode == 200; @@ -139,7 +139,7 @@ public class Http { } public boolean cached() { - return cacheStatus.equals("HIT"); + return cacheStatuses[0].equals("HIT") || cacheStatuses[1].equals("HIT"); } @Override diff --git a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java index a81c25f7..460f34dd 100644 --- a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java +++ b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java @@ -44,7 +44,7 @@ public class ContainerSolverManager { new CroesusProfit(), new ChronomatronSolver(), new SuperpairsSolver(), - new UltrasequencerSolver() + UltrasequencerSolver.INSTANCE }; } |