diff options
Diffstat (limited to 'src/main')
54 files changed, 1332 insertions, 479 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index 2987f493..e334ef86 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -8,8 +8,8 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.debug.Debug; import de.hysky.skyblocker.skyblock.*; import de.hysky.skyblocker.skyblock.chat.ChatRuleAnnouncementScreen; -import de.hysky.skyblocker.skyblock.crimson.kuudra.Kuudra; import de.hysky.skyblocker.skyblock.chat.ChatRulesHandler; +import de.hysky.skyblocker.skyblock.crimson.kuudra.Kuudra; import de.hysky.skyblocker.skyblock.dungeon.*; import de.hysky.skyblocker.skyblock.dungeon.partyfinder.PartyFinderScreen; import de.hysky.skyblocker.skyblock.dungeon.puzzle.*; @@ -22,6 +22,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.FarmingHud; import de.hysky.skyblocker.skyblock.garden.VisitorHelper; import de.hysky.skyblocker.skyblock.item.*; import de.hysky.skyblocker.skyblock.item.tooltip.BackpackPreview; @@ -108,8 +109,10 @@ public class SkyblockerMod implements ClientModInitializer { BackpackPreview.init(); QuickNav.init(); ItemCooldowns.init(); + TabHud.init(); DwarvenHud.init(); CrystalsHud.init(); + FarmingHud.init(); CrystalsLocationsManager.init(); ChatMessageListener.init(); Shortcuts.init(); @@ -118,7 +121,6 @@ public class SkyblockerMod implements ClientModInitializer { DiscordRPCManager.init(); LividColor.init(); FishingHelper.init(); - TabHud.init(); DungeonMap.init(); DungeonManager.init(); DungeonBlaze.init(); @@ -164,7 +166,6 @@ public class SkyblockerMod implements ClientModInitializer { Scheduler.INSTANCE.scheduleCyclic(BackpackPreview::tick, 50); Scheduler.INSTANCE.scheduleCyclic(DwarvenHud::update, 40); Scheduler.INSTANCE.scheduleCyclic(CrystalsHud::update, 40); - Scheduler.INSTANCE.scheduleCyclic(CrystalsLocationsManager::update, 40); Scheduler.INSTANCE.scheduleCyclic(PlayerListMgr::updateList, 20); } diff --git a/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java b/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java index c33e2f54..07109b46 100644 --- a/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/config/HudConfigScreen.java @@ -2,82 +2,141 @@ package de.hysky.skyblocker.config; import de.hysky.skyblocker.skyblock.tabhud.widget.Widget; import de.hysky.skyblocker.utils.render.RenderHelper; -import it.unimi.dsi.fastutil.ints.IntIntImmutablePair; -import it.unimi.dsi.fastutil.ints.IntIntPair; +import it.unimi.dsi.fastutil.ints.IntIntMutablePair; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; +import net.minecraft.util.math.MathHelper; import java.awt.*; +import java.util.List; +/** + * A screen for configuring the positions of HUD widgets. + * <p> + * This class takes care of rendering the widgets, dragging them, and resetting their positions. + * Create one subclass for each collection of HUD widgets that are displayed at the same time. + * (i.e. one for dwarven mines, one for the end, etc.) See an implementation for an example. + */ public abstract class HudConfigScreen extends Screen { - private final Widget widget; private final Screen parent; + private final List<Widget> widgets; - private int hudX = 0; - private int hudY = 0; - public HudConfigScreen(Text title, Widget widget, Screen parent) { + private Widget draggingWidget; + private double mouseClickRelativeX; + private double mouseClickRelativeY; + + /** + * Creates a new HudConfigScreen with the passed title, parent, and widget + * @param title the title of the screen + * @param parent the parent screen + * @param widget the widget to configure + */ + public HudConfigScreen(Text title, Screen parent, Widget widget) { + this(title, parent, List.of(widget)); + } + + /** + * Creates a new HudConfigScreen with the passed title, parent, and widgets + * @param title the title of the screen + * @param parent the parent screen + * @param widgets the widgets to configure + */ + public HudConfigScreen(Text title, Screen parent, List<Widget> widgets) { super(title); - this.widget = widget; this.parent = parent; - - int[] posFromConfig = getPosFromConfig(SkyblockerConfigManager.get()); - hudX = posFromConfig[0]; - hudY = posFromConfig[1]; + this.widgets = widgets; + resetPos(); } @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { + public final void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); - renderBackground(context, mouseX, mouseY, delta); - renderWidget(context, hudX, hudY); + renderWidget(context, widgets); context.drawCenteredTextWithShadow(textRenderer, "Right Click To Reset Position", width / 2, height / 2, Color.GRAY.getRGB()); } + /** + * Renders the widgets using the default {@link Widget#render(DrawContext, boolean)} method. Override to change the behavior. + * @param context the context to render in + * @param widgets the widgets to render + */ + protected void renderWidget(DrawContext context, List<Widget> widgets) { + for (Widget widget : widgets) { + widget.render(context, SkyblockerConfigManager.get().general.tabHud.enableHudBackground); + } + } + @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - IntIntPair dims = getDimensions(); - if (RenderHelper.pointIsInArea(mouseX, mouseY, hudX, hudY, hudX + dims.leftInt(), hudY + dims.rightInt()) && button == 0) { - hudX = (int) Math.max(Math.min(mouseX - (double) dims.leftInt() / 2, this.width - dims.leftInt()), 0); - hudY = (int) Math.max(Math.min(mouseY - (double) dims.rightInt() / 2, this.height - dims.rightInt()), 0); + public final boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (button == 0 && draggingWidget != null) { + draggingWidget.setX((int) MathHelper.clamp(mouseX - mouseClickRelativeX, 0, this.width - draggingWidget.getWidth())); + draggingWidget.setY((int) MathHelper.clamp(mouseY - mouseClickRelativeY, 0, this.height - draggingWidget.getHeight())); } return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (button == 1) { - IntIntPair dims = getDimensions(); - hudX = this.width / 2 - dims.leftInt(); - hudY = this.height / 2 - dims.rightInt(); + public final boolean mouseClicked(double mouseX, double mouseY, int button) { + if (button == 0) { + for (Widget widget : widgets) { + if (RenderHelper.pointIsInArea(mouseX, mouseY, widget.getX(), widget.getY(), widget.getX() + widget.getWidth(), widget.getY() + widget.getHeight())) { + draggingWidget = widget; + mouseClickRelativeX = mouseX - widget.getX(); + mouseClickRelativeY = mouseY - widget.getY(); + break; + } + } + } else if (button == 1) { + resetPos(); } return super.mouseClicked(mouseX, mouseY, button); } - abstract protected int[] getPosFromConfig(SkyblockerConfig config); + @Override + public final boolean mouseReleased(double mouseX, double mouseY, int button) { + draggingWidget = null; + return super.mouseReleased(mouseX, mouseY, button); + } - protected IntIntPair getDimensions() { - return new IntIntImmutablePair(widget.getHeight(), widget.getWidth()); + /** + * Resets the positions of the widgets to the positions in the config. Override to change the behavior. + */ + protected void resetPos() { + List<IntIntMutablePair> configPositions = getConfigPos(SkyblockerConfigManager.get()); + if (configPositions.size() != widgets.size()) { + throw new IllegalStateException("The number of positions (" + configPositions.size() + ") does not match the number of widgets (" + widgets.size() + ")"); + } + for (int i = 0; i < widgets.size(); i++) { + Widget widget = widgets.get(i); + IntIntMutablePair configPos = configPositions.get(i); + widget.setX(configPos.leftInt()); + widget.setY(configPos.rightInt()); + } } + /** + * Returns the positions of the widgets in the config + * @param config the config to get the positions from + * @return the positions of the widgets + */ + protected abstract List<IntIntMutablePair> getConfigPos(SkyblockerConfig config); + @Override - public void close() { + public final void close() { SkyblockerConfig skyblockerConfig = SkyblockerConfigManager.get(); - savePos(skyblockerConfig, hudX, hudY); + savePos(skyblockerConfig, widgets); SkyblockerConfigManager.save(); client.setScreen(parent); } /** - * This method should save the passed position to the config + * Saves the passed positions to the config. * <p> * NOTE: The parent class will call {@link SkyblockerConfigManager#save()} right after this method * @param configManager the config so you don't have to get it - * @param x x - * @param y y + * @param widgets the widgets to save */ - abstract protected void savePos(SkyblockerConfig configManager, int x, int y); - - abstract protected void renderWidget(DrawContext context, int x, int y); + protected abstract void savePos(SkyblockerConfig configManager, List<Widget> widgets); } diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java index a86b0111..a3e710c1 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java @@ -267,6 +267,9 @@ public class SkyblockerConfig { public int tabHudScale = 100; @SerialEntry + public boolean enableHudBackground = true; + + @SerialEntry public boolean plainPlayerNames = false; @SerialEntry @@ -945,9 +948,6 @@ public class SkyblockerConfig { public DwarvenHudStyle style = DwarvenHudStyle.SIMPLE; @SerialEntry - public boolean enableBackground = true; - - @SerialEntry public int x = 10; @SerialEntry @@ -1063,9 +1063,6 @@ public class SkyblockerConfig { public boolean hudEnabled = true; @SerialEntry - public boolean enableBackground = true; - - @SerialEntry public boolean waypoint = true; @SerialEntry @@ -1090,12 +1087,26 @@ public class SkyblockerConfig { public static class Garden { @SerialEntry + public FarmingHud farmingHud = new FarmingHud(); + + @SerialEntry public boolean dicerTitlePrevent = true; @SerialEntry public boolean visitorHelper = true; } + public static class FarmingHud { + @SerialEntry + public boolean enableHud = true; + + @SerialEntry + public int x; + + @SerialEntry + public int y; + } + public static class Slayer { @SerialEntry public EndermanSlayer endermanSlayer = new EndermanSlayer(); @@ -1106,10 +1117,13 @@ public class SkyblockerConfig { public static class EndermanSlayer { @SerialEntry - public boolean highlightNukekubiHeads = true; + public boolean enableYangGlyphsNotification = true; @SerialEntry public boolean highlightBeacons = true; + + @SerialEntry + public boolean highlightNukekubiHeads = true; } public static class VampireSlayer { @@ -1199,6 +1213,7 @@ public class SkyblockerConfig { @SerialEntry public ChatRuleConfig chatRuleConfig = new ChatRuleConfig(); } + public static class ChatRuleConfig { @SerialEntry public int announcementLength = 60; diff --git a/src/main/java/de/hysky/skyblocker/config/categories/DwarvenMinesCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/DwarvenMinesCategory.java index 97b48bc4..4ae0fc35 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/DwarvenMinesCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/DwarvenMinesCategory.java @@ -76,13 +76,6 @@ public class DwarvenMinesCategory { .text(Text.translatable("text.skyblocker.open")) .action((screen, opt) -> MinecraftClient.getInstance().setScreen(new DwarvenHudConfigScreen(screen))) .build()) - .option(Option.<Boolean>createBuilder() - .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground")) - .binding(defaults.locations.dwarvenMines.dwarvenHud.enableBackground, - () -> config.locations.dwarvenMines.dwarvenHud.enableBackground, - newValue -> config.locations.dwarvenMines.dwarvenHud.enableBackground = newValue) - .controller(ConfigUtils::createBooleanController) - .build()) .build()) //crystal HUD .group(OptionGroup.createBuilder() 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 afd688d8..23ce7bb6 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -107,6 +107,14 @@ public class GeneralCategory { .controller(opt -> IntegerSliderControllerBuilder.create(opt).range(10, 200).step(1)) .build()) .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.general.tabHud.enableHudBackground")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.general.tabHud.enableHudBackground.@Tooltip"))) + .binding(defaults.general.tabHud.enableHudBackground, + () -> config.general.tabHud.enableHudBackground, + newValue -> config.general.tabHud.enableHudBackground = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Boolean>createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.general.tabHud.plainPlayerNames")) .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.general.tabHud.plainPlayerNames.@Tooltip"))) .binding(defaults.general.tabHud.plainPlayerNames, 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 d97513f8..86ed3f6c 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java @@ -4,6 +4,7 @@ import de.hysky.skyblocker.config.ConfigUtils; import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.skyblock.end.EndHudConfigScreen; import de.hysky.skyblocker.skyblock.end.TheEnd; +import de.hysky.skyblocker.skyblock.garden.FarmingHudConfigScreen; import dev.isxander.yacl3.api.*; import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; import net.minecraft.client.MinecraftClient; @@ -91,13 +92,6 @@ public class LocationsCategory { .controller(ConfigUtils::createBooleanController) .build()) .option(Option.<Boolean>createBuilder() - .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground")) // Reusing that string cuz sure - .binding(defaults.locations.end.enableBackground, - () -> config.locations.end.enableBackground, - newValue -> config.locations.end.enableBackground = newValue) - .controller(ConfigUtils::createBooleanController) - .build()) - .option(Option.<Boolean>createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.locations.end.waypoint")) .binding(defaults.locations.end.waypoint, () -> config.locations.end.waypoint, @@ -147,6 +141,18 @@ public class LocationsCategory { .name(Text.translatable("text.autoconfig.skyblocker.option.locations.garden")) .collapsed(false) .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.garden.farmingHud.enableHud")) + .binding(defaults.locations.garden.farmingHud.enableHud, + () -> config.locations.garden.farmingHud.enableHud, + newValue -> config.locations.garden.farmingHud.enableHud = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(ButtonOption.createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.garden.farmingHud.config")) + .text(Text.translatable("text.skyblocker.open")) + .action((screen, opt) -> MinecraftClient.getInstance().setScreen(new FarmingHudConfigScreen(screen))) + .build()) + .option(Option.<Boolean>createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.locations.garden.dicerTitlePrevent")) .binding(defaults.locations.garden.dicerTitlePrevent, () -> config.locations.garden.dicerTitlePrevent, @@ -154,7 +160,7 @@ public class LocationsCategory { .controller(ConfigUtils::createBooleanController) .build()) .option(Option.<Boolean>createBuilder() - .name(Text.translatable("text.autoconfig.skyblocker.option.general.visitorHelper")) + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.garden.visitorHelper")) .binding(defaults.locations.garden.visitorHelper, () -> config.locations.garden.visitorHelper, newValue -> config.locations.garden.visitorHelper = newValue) diff --git a/src/main/java/de/hysky/skyblocker/config/categories/SlayersCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/SlayersCategory.java index 19b30937..005bebab 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/SlayersCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/SlayersCategory.java @@ -22,10 +22,10 @@ public class SlayersCategory { .name(Text.translatable("text.autoconfig.skyblocker.option.slayer.endermanSlayer")) .collapsed(true) .option(Option.<Boolean>createBuilder() - .name(Text.translatable("text.autoconfig.skyblocker.option.slayer.endermanSlayer.highlightNukekubiHeads")) - .binding(defaults.slayer.endermanSlayer.highlightNukekubiHeads, - () -> config.slayer.endermanSlayer.highlightNukekubiHeads, - newValue -> config.slayer.endermanSlayer.highlightNukekubiHeads = newValue) + .name(Text.translatable("text.autoconfig.skyblocker.option.slayer.endermanSlayer.enableYangGlyphsNotification")) + .binding(defaults.slayer.endermanSlayer.enableYangGlyphsNotification, + () -> config.slayer.endermanSlayer.enableYangGlyphsNotification, + newValue -> config.slayer.endermanSlayer.enableYangGlyphsNotification = newValue) .controller(ConfigUtils::createBooleanController) .build()) .option(Option.<Boolean>createBuilder() @@ -35,6 +35,13 @@ public class SlayersCategory { newValue -> config.slayer.endermanSlayer.highlightBeacons = newValue) .controller(ConfigUtils::createBooleanController) .build()) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.slayer.endermanSlayer.highlightNukekubiHeads")) + .binding(defaults.slayer.endermanSlayer.highlightNukekubiHeads, + () -> config.slayer.endermanSlayer.highlightNukekubiHeads, + newValue -> config.slayer.endermanSlayer.highlightNukekubiHeads = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) .build()) //Vampire Slayer diff --git a/src/main/java/de/hysky/skyblocker/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayNetworkHandlerMixin.java index 4c414212..8397292b 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayNetworkHandlerMixin.java @@ -4,20 +4,19 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.WrapWithCondition; import com.llamalad7.mixinextras.sugar.Local; import de.hysky.skyblocker.skyblock.FishingHelper; -import de.hysky.skyblocker.skyblock.end.TheEnd; import de.hysky.skyblocker.skyblock.dungeon.DungeonScore; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.skyblock.end.BeaconHighlighter; +import de.hysky.skyblocker.skyblock.end.TheEnd; import de.hysky.skyblocker.skyblock.waypoint.MythologicalRitual; import de.hysky.skyblocker.utils.SlayerUtils; import de.hysky.skyblocker.utils.Utils; import net.minecraft.block.Blocks; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityStatuses; import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.LivingEntity; import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket; import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; @@ -25,6 +24,7 @@ import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; import net.minecraft.util.Identifier; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; @@ -32,6 +32,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ClientPlayNetworkHandler.class) public abstract class ClientPlayNetworkHandlerMixin { + @Shadow + private ClientWorld world; + @Inject(method = "onBlockUpdate", at = @At("RETURN")) private void skyblocker$onBlockUpdate(BlockUpdateS2CPacket packet, CallbackInfo ci) { if (Utils.isInTheEnd() && SlayerUtils.isInSlayer()) { @@ -42,9 +45,16 @@ public abstract class ClientPlayNetworkHandlerMixin { } } - @ModifyVariable(method = "onItemPickupAnimation", at = @At(value = "STORE", ordinal = 0)) - private ItemEntity skyblocker$onItemPickup(ItemEntity itemEntity, @Local LivingEntity collector) { - DungeonManager.onItemPickup(itemEntity, collector, collector == MinecraftClient.getInstance().player); + @Inject(method = "method_37472", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;removeEntity(ILnet/minecraft/entity/Entity$RemovalReason;)V")) + private void skyblocker$onItemDestroy(int entityId, CallbackInfo ci) { + if (world.getEntityById(entityId) instanceof ItemEntity itemEntity) { + DungeonManager.onItemPickup(itemEntity); + } + } + + @ModifyVariable(method = "onItemPickupAnimation", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;removeEntity(ILnet/minecraft/entity/Entity$RemovalReason;)V", ordinal = 0)) + private ItemEntity skyblocker$onItemPickup(ItemEntity itemEntity) { + DungeonManager.onItemPickup(itemEntity); return itemEntity; } diff --git a/src/main/java/de/hysky/skyblocker/mixin/DataTrackerMixin.java b/src/main/java/de/hysky/skyblocker/mixin/DataTrackerMixin.java index 03786876..d9db5dae 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/DataTrackerMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/DataTrackerMixin.java @@ -1,19 +1,50 @@ package de.hysky.skyblocker.mixin; +import com.llamalad7.mixinextras.sugar.Local; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.mixin.accessor.EndermanEntityAccessor; +import de.hysky.skyblocker.skyblock.entity.MobGlow; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.entity.data.DataTracker; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import de.hysky.skyblocker.utils.Utils; -import net.minecraft.entity.data.DataTracker; +import java.util.Optional; @Mixin(DataTracker.class) -public class DataTrackerMixin { +public abstract class DataTrackerMixin { + @Shadow + @Final + private Entity trackedEntity; + + @SuppressWarnings("ConstantValue") + @Inject(method = "writeUpdatedEntries", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/data/DataTracker;copyToFrom(Lnet/minecraft/entity/data/DataTracker$Entry;Lnet/minecraft/entity/data/DataTracker$SerializedEntry;)V")) + private <T> void skyblocker$onWriteUpdatedEntries(CallbackInfo ci, @Local DataTracker.Entry<T> entry, @Local DataTracker.SerializedEntry<T> serializedEntry) { + if (Utils.isInTheEnd() && SkyblockerConfigManager.get().slayer.endermanSlayer.enableYangGlyphsNotification && entry.getData() == EndermanEntityAccessor.getCARRIED_BLOCK() && entry.get() instanceof Optional<?> value && value.isPresent() && value.get() instanceof BlockState state && state.isOf(Blocks.BEACON) && ((Optional<?>) serializedEntry.value()).isEmpty()) { + MinecraftClient client = MinecraftClient.getInstance(); + if (MobGlow.getArmorStands(trackedEntity).stream().anyMatch(armorStand -> armorStand.getName().getString().contains(client.getSession().getUsername()))) { + client.inGameHud.setTitleTicks(5, 20, 10); + client.inGameHud.setTitle(Text.literal("Yang Glyph!").formatted(Formatting.RED)); + client.player.playSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 100f, 0.1f); + } + } + } - @Inject(method = "copyToFrom", at = @At(value = "NEW", target = "Ljava/lang/IllegalStateException;", shift = At.Shift.BEFORE), cancellable = true) - public void skyblocker$ignoreInvalidDataExceptions(CallbackInfo ci) { - //These exceptions cause annoying small lag spikes for some reason - if (Utils.isOnHypixel()) ci.cancel(); - } + @SuppressWarnings({"MixinAnnotationTarget", "UnresolvedMixinReference"}) + @Inject(method = "copyToFrom", at = @At(value = "NEW", target = "Ljava/lang/IllegalStateException;"), cancellable = true) + public void skyblocker$ignoreInvalidDataExceptions(CallbackInfo ci) { + //These exceptions cause annoying small lag spikes for some reason + if (Utils.isOnHypixel()) ci.cancel(); + } } diff --git a/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java b/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java index 5e3daf3c..75c516df 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java @@ -9,6 +9,7 @@ import de.hysky.skyblocker.skyblock.FancyStatusBars; import de.hysky.skyblocker.skyblock.dungeon.DungeonMap; import de.hysky.skyblocker.skyblock.dungeon.DungeonScore; import de.hysky.skyblocker.skyblock.dungeon.DungeonScoreHUD; +import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.skyblock.item.HotbarSlotLock; import de.hysky.skyblocker.skyblock.item.ItemCooldowns; import de.hysky.skyblocker.skyblock.item.ItemProtection; @@ -91,7 +92,7 @@ public abstract class InGameHudMixin { ci.cancel(); if (Utils.isInDungeons() && DungeonScore.isDungeonStarted()) { - if (SkyblockerConfigManager.get().locations.dungeons.enableMap) DungeonMap.render(context.getMatrices()); + if (SkyblockerConfigManager.get().locations.dungeons.enableMap && !DungeonManager.isInBoss()) DungeonMap.render(context.getMatrices()); if (SkyblockerConfigManager.get().locations.dungeons.dungeonScore.enableScoreHUD) DungeonScoreHUD.render(context); } } diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/BeaconBlockEntityRendererInvoker.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/BeaconBlockEntityRendererInvoker.java index 0b607fce..e470cdae 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/accessor/BeaconBlockEntityRendererInvoker.java +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/BeaconBlockEntityRendererInvoker.java @@ -11,6 +11,6 @@ public interface BeaconBlockEntityRendererInvoker { @SuppressWarnings("unused") @Invoker("renderBeam") static void renderBeam(MatrixStack matrices, VertexConsumerProvider vertexConsumers, float tickDelta, long worldTime, int yOffset, int maxY, float[] color) { - throw new IllegalStateException("Mixin invoker failed to apply."); + throw new UnsupportedOperationException(); } } diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/EndermanEntityAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/EndermanEntityAccessor.java new file mode 100644 index 00000000..b7bcd95c --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/EndermanEntityAccessor.java @@ -0,0 +1,17 @@ +package de.hysky.skyblocker.mixin.accessor; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.data.TrackedData; +import net.minecraft.entity.mob.EndermanEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Optional; + +@Mixin(EndermanEntity.class) +public interface EndermanEntityAccessor { + @Accessor + static TrackedData<Optional<BlockState>> getCARRIED_BLOCK() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/MessageHandlerAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/MessageHandlerAccessor.java new file mode 100644 index 00000000..6e5793e3 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/MessageHandlerAccessor.java @@ -0,0 +1,14 @@ +package de.hysky.skyblocker.mixin.accessor; + +import net.minecraft.client.network.message.MessageHandler; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.time.Instant; + +@Mixin(MessageHandler.class) +public interface MessageHandlerAccessor { + @Invoker + void invokeAddToChatLog(Text message, Instant timestamp); +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/PlayerListHudAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/PlayerListHudAccessor.java index d82c568f..c982249a 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/accessor/PlayerListHudAccessor.java +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/PlayerListHudAccessor.java @@ -9,9 +9,8 @@ import java.util.Comparator; @Mixin(PlayerListHud.class) public interface PlayerListHudAccessor { - @Accessor("ENTRY_ORDERING") static Comparator<PlayerListEntry> getOrdering() { - throw new AssertionError(); + throw new UnsupportedOperationException(); } } diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/RecipeBookWidgetAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/RecipeBookWidgetAccessor.java index aecdf9b7..30aad00c 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/accessor/RecipeBookWidgetAccessor.java +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/RecipeBookWidgetAccessor.java @@ -9,6 +9,7 @@ import org.spongepowered.asm.mixin.gen.Accessor; public interface RecipeBookWidgetAccessor { @Accessor String getSearchText(); + @Accessor TextFieldWidget getSearchField(); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesHandler.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesHandler.java index 13115bee..2a103d13 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesHandler.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesHandler.java @@ -5,8 +5,8 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.mojang.serialization.Codec; import com.mojang.serialization.JsonOps; - import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.mixin.accessor.MessageHandlerAccessor; import de.hysky.skyblocker.utils.Http; import de.hysky.skyblocker.utils.Utils; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; @@ -21,10 +21,10 @@ import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.BufferedWriter; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; +import java.time.Instant; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -53,16 +53,16 @@ public class ChatRulesHandler { private static void loadChatRules() { try (BufferedReader reader = Files.newBufferedReader(CHAT_RULE_FILE)) { Map<String, List<ChatRule>> chatRules = MAP_CODEC.parse(JsonOps.INSTANCE, JsonParser.parseReader(reader)).result().orElseThrow(); - LOGGER.info("[Sky: " + chatRules.toString()); - + LOGGER.info("[Skyblocker Chat Rules]: {}", chatRules); + chatRuleList.addAll(chatRules.get("rules")); - LOGGER.info("[Skyblocker] Loaded chat rules"); + LOGGER.info("[Skyblocker Chat Rules] Loaded chat rules"); } catch (NoSuchFileException e) { registerDefaultChatRules(); - LOGGER.warn("[Skyblocker] chat rule file not found, using default rules. This is normal when using for the first time."); + LOGGER.warn("[Skyblocker Chat Rules] chat rules file not found, using default rules. This is normal when using for the first time."); } catch (Exception e) { - LOGGER.error("[Skyblocker] Failed to load shortcuts file", e); + LOGGER.error("[Skyblocker Chat Rules] Failed to load chat rules file", e); } } @@ -92,7 +92,7 @@ public class ChatRulesHandler { locations.put(entry.getValue().getAsString().replace(" ", "").toLowerCase(), entry.getKey()); } } catch (Exception e) { - LOGGER.error("[Skyblocker] Failed to load locations!", e); + LOGGER.error("[Skyblocker Chat Rules] Failed to load locations!", e); } } @@ -101,9 +101,9 @@ public class ChatRulesHandler { chatRuleJson.add("rules", ChatRule.LIST_CODEC.encodeStart(JsonOps.INSTANCE, chatRuleList).result().orElseThrow()); try (BufferedWriter writer = Files.newBufferedWriter(CHAT_RULE_FILE)) { SkyblockerMod.GSON.toJson(chatRuleJson, writer); - LOGGER.info("[Skyblocker] Saved chat rules file"); + LOGGER.info("[Skyblocker Chat Rules] Saved chat rules file"); } catch (Exception e) { - LOGGER.error("[Skyblocker] Failed to save chat rules file", e); + LOGGER.error("[Skyblocker Chat Rules] Failed to save chat rules file", e); } } @@ -136,9 +136,12 @@ public class ChatRulesHandler { CLIENT.player.sendMessage(newMessage, true); } - //hide message + //show replacement message in chat + //bypass MessageHandler#onGameMessage to avoid activating chat rules again if (!rule.getHideMessage() && CLIENT.player != null) { - CLIENT.player.sendMessage(newMessage, false); + CLIENT.inGameHud.getChatHud().addMessage(newMessage); + ((MessageHandlerAccessor) CLIENT.getMessageHandler()).invokeAddToChatLog(newMessage, Instant.now()); + CLIENT.getNarratorManager().narrateSystemMessage(newMessage); } //play sound diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java index 293d301f..f2986ec0 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java @@ -4,48 +4,65 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.scheduler.Scheduler; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.MapRenderer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.FilledMapItem; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.item.map.MapState; -import net.minecraft.nbt.NbtCompound; -import org.apache.commons.lang3.StringUtils; public class DungeonMap { + private static final int DEFAULT_MAP_ID = 1024; + private static Integer cachedMapId = null; + + public static void init() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") + .then(ClientCommandManager.literal("hud") + .then(ClientCommandManager.literal("dungeon") + .executes(Scheduler.queueOpenScreenCommand(DungeonMapConfigScreen::new)) + ) + ) + )); + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> reset()); + } + public static void render(MatrixStack matrices) { MinecraftClient client = MinecraftClient.getInstance(); if (client.player == null || client.world == null) return; - ItemStack item = client.player.getInventory().main.get(8); - NbtCompound tag = item.getNbt(); - - if (tag != null && tag.contains("map")) { - String tag2 = tag.asString(); - tag2 = StringUtils.substringBetween(tag2, "map:", "}"); - int mapid = Integer.parseInt(tag2); - VertexConsumerProvider.Immediate vertices = client.getBufferBuilders().getEffectVertexConsumers(); - MapRenderer map = client.gameRenderer.getMapRenderer(); - MapState state = FilledMapItem.getMapState(mapid, client.world); - float scaling = SkyblockerConfigManager.get().locations.dungeons.mapScaling; - int x = SkyblockerConfigManager.get().locations.dungeons.mapX; - int y = SkyblockerConfigManager.get().locations.dungeons.mapY; - - if (state == null) return; - matrices.push(); - matrices.translate(x, y, 0); - matrices.scale(scaling, scaling, 0f); - map.draw(matrices, vertices, mapid, state, false, 15728880); - vertices.draw(); - matrices.pop(); - } + + int mapId = getMapId(client.player.getInventory().main.get(8)); + + MapState state = FilledMapItem.getMapState(mapId, client.world); + if (state == null) return; + + int x = SkyblockerConfigManager.get().locations.dungeons.mapX; + int y = SkyblockerConfigManager.get().locations.dungeons.mapY; + float scaling = SkyblockerConfigManager.get().locations.dungeons.mapScaling; + VertexConsumerProvider.Immediate vertices = client.getBufferBuilders().getEffectVertexConsumers(); + MapRenderer mapRenderer = client.gameRenderer.getMapRenderer(); + + matrices.push(); + matrices.translate(x, y, 0); + matrices.scale(scaling, scaling, 0f); + mapRenderer.draw(matrices, vertices, mapId, state, false, LightmapTextureManager.MAX_LIGHT_COORDINATE); + vertices.draw(); + matrices.pop(); } - public static void init() { //Todo: consider renaming the command to a more general name since it'll also have dungeon score and maybe other stuff in the future - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") - .then(ClientCommandManager.literal("hud") - .then(ClientCommandManager.literal("dungeonmap") - .executes(Scheduler.queueOpenScreenCommand(DungeonMapConfigScreen::new)))))); + public static int getMapId(ItemStack stack) { + if (stack.isOf(Items.FILLED_MAP)) { + @SuppressWarnings("DataFlowIssue") + int mapId = FilledMapItem.getMapId(stack); + cachedMapId = mapId; + return mapId; + } else return cachedMapId != null ? cachedMapId : DEFAULT_MAP_ID; + } + + private static void reset() { + cachedMapId = null; } -}
\ No newline at end of file +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java index a207ddc7..d5d57e70 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java @@ -15,6 +15,7 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.debug.Debug; +import de.hysky.skyblocker.skyblock.dungeon.DungeonMap; import de.hysky.skyblocker.utils.Constants; import de.hysky.skyblocker.utils.Tickable; import de.hysky.skyblocker.utils.Utils; @@ -514,10 +515,7 @@ public class DungeonManager { */ @SuppressWarnings("JavadocReference") private static void update() { - if (!Utils.isInDungeons()) { - if (mapEntrancePos != null) { - reset(); - } + if (!Utils.isInDungeons() || isInBoss()) { return; } MinecraftClient client = MinecraftClient.getInstance(); @@ -529,11 +527,7 @@ public class DungeonManager { physicalEntrancePos = DungeonMapUtils.getPhysicalRoomPos(playerPos); currentRoom = newRoom(Room.Type.ENTRANCE, physicalEntrancePos); } - ItemStack stack = client.player.getInventory().main.get(8); - if (!stack.isOf(Items.FILLED_MAP)) { - return; - } - MapState map = FilledMapItem.getMapState(FilledMapItem.getMapId(stack), client.world); + MapState map = FilledMapItem.getMapState(DungeonMap.getMapId(client.player.getInventory().main.get(8)), client.world); if (map == null) { return; } @@ -616,7 +610,7 @@ public class DungeonManager { String message = text.getString(); - if (overlay && isCurrentRoomMatched()) { + if (isCurrentRoomMatched()) { currentRoom.onChatMessage(message); } @@ -666,7 +660,7 @@ public class DungeonManager { @SuppressWarnings("JavadocReference") private static ActionResult onUseBlock(World world, BlockHitResult hitResult) { if (isCurrentRoomMatched()) { - currentRoom.onUseBlock(world, hitResult); + currentRoom.onUseBlock(world, hitResult.getBlockPos()); } return ActionResult.PASS; } @@ -677,16 +671,10 @@ public class DungeonManager { * If the collector is the player, {@link #currentRoom} is used as an optimization. */ @SuppressWarnings("JavadocReference") - public static void onItemPickup(ItemEntity itemEntity, LivingEntity collector, boolean isPlayer) { - if (isPlayer) { - if (isCurrentRoomMatched()) { - currentRoom.onItemPickup(itemEntity, collector); - } - } else { - Room room = getRoomAtPhysical(collector.getPos()); - if (isRoomMatched(room)) { - room.onItemPickup(itemEntity, collector); - } + public static void onItemPickup(ItemEntity itemEntity) { + Room room = getRoomAtPhysical(itemEntity.getPos()); + if (isRoomMatched(room)) { + room.onItemPickup(itemEntity); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java index a1bafc20..5b20b48f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java @@ -29,12 +29,10 @@ import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.world.ClientWorld; import net.minecraft.command.argument.EnumArgumentType; import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.mob.AmbientEntity; import net.minecraft.registry.Registries; import net.minecraft.text.Text; import net.minecraft.util.StringIdentifiable; -import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; @@ -54,6 +52,7 @@ import java.util.regex.Pattern; public class Room implements Tickable, Renderable { private static final Pattern SECRET_INDEX = Pattern.compile("^(\\d+)"); private static final Pattern SECRETS = Pattern.compile("§7(\\d{1,2})/(\\d{1,2}) Secrets"); + private static final String LOCKED_CHEST = "That chest is locked!"; private static final Vec3d DOOR_SIZE = new Vec3d(3, 4, 3); protected static final float[] RED_COLOR_COMPONENTS = {1, 0, 0}; protected static final float[] GREEN_COLOR_COMPONENTS = {0, 1, 0}; @@ -99,6 +98,8 @@ public class Room implements Tickable, Renderable { protected List<Tickable> tickables = new ArrayList<>(); protected List<Renderable> renderables = new ArrayList<>(); + private BlockPos lastChestSecret; + private long lastChestSecretTime; /** * Stores the next room in the dungeon. Currently only used if the next room is the fairy room. */ @@ -207,7 +208,7 @@ public class Room implements Tickable, Renderable { SecretWaypoint.Category category = SecretWaypoint.Category.CategoryArgumentType.getCategory(context, "category"); Text waypointName = context.getArgument("name", Text.class); addCustomWaypoint(secretIndex, category, waypointName, pos); - context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.dungeons.secrets.customWaypointAdded", pos.getX(), pos.getY(), pos.getZ(), name, secretIndex, category, waypointName))); + context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.stringifiedTranslatable("skyblocker.dungeons.secrets.customWaypointAdded", pos.getX(), pos.getY(), pos.getZ(), name, secretIndex, category, waypointName))); } /** @@ -241,7 +242,7 @@ public class Room implements Tickable, Renderable { protected void removeCustomWaypoint(CommandContext<FabricClientCommandSource> context, BlockPos pos) { SecretWaypoint waypoint = removeCustomWaypoint(pos); if (waypoint != null) { - context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.dungeons.secrets.customWaypointRemoved", pos.getX(), pos.getY(), pos.getZ(), name, waypoint.secretIndex, waypoint.category, waypoint.name))); + context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.stringifiedTranslatable("skyblocker.dungeons.secrets.customWaypointRemoved", pos.getX(), pos.getY(), pos.getZ(), name, waypoint.secretIndex, waypoint.category, waypoint.name))); } else { context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.dungeons.secrets.customWaypointNotFound", pos.getX(), pos.getY(), pos.getZ(), name))); } @@ -549,11 +550,14 @@ public class Room implements Tickable, Renderable { } /** - * Sets all secrets as found if {@link #isAllSecretsFound(String)}. + * Sets all secrets as found if {@link #isAllSecretsFound(String)} and sets {@link #lastChestSecret} as missing if message equals {@link #LOCKED_CHEST}. */ protected void onChatMessage(String message) { if (isAllSecretsFound(message)) { secretWaypoints.values().forEach(SecretWaypoint::setFound); + } else if (LOCKED_CHEST.equals(message) && lastChestSecretTime + 1000 > System.currentTimeMillis() && lastChestSecret != null) { + secretWaypoints.column(lastChestSecret).values().stream().filter(SecretWaypoint::needsInteraction).findAny() + .ifPresent(secretWaypoint -> markSecretsAndLogInfo(secretWaypoint, false, "[Skyblocker Dungeon Secrets] Detected locked chest interaction, setting secret #{} as missing", secretWaypoint.secretIndex)); } } @@ -572,58 +576,72 @@ public class Room implements Tickable, Renderable { } /** - * Marks the secret at the interaction position as found when the player interacts with a chest or a player head, - * if there is a secret at the interaction position. + * Marks the secret at the interaction position as found when the player interacts with a chest, player head, or lever + * if there is a secret at the interaction position and saves the position to {@link #lastChestSecret} if the block is a chest. * - * @param world the world to get the block from - * @param hitResult the block being interacted with - * @see #onSecretFound(SecretWaypoint, String, Object...) + * @param world the world to get the block from + * @param pos the position of the block being interacted with + * @see #markSecretsFoundAndLogInfo(SecretWaypoint, String, Object...) */ - protected void onUseBlock(World world, BlockHitResult hitResult) { - BlockState state = world.getBlockState(hitResult.getBlockPos()); - if (state.isOf(Blocks.CHEST) || state.isOf(Blocks.PLAYER_HEAD) || state.isOf(Blocks.PLAYER_WALL_HEAD)) { - secretWaypoints.column(hitResult.getBlockPos()).values().stream().filter(SecretWaypoint::needsInteraction).findAny() - .ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} interaction, setting secret #{} as found", secretWaypoint.category, secretWaypoint.secretIndex)); + protected void onUseBlock(World world, BlockPos pos) { + BlockState state = world.getBlockState(pos); + if ((state.isOf(Blocks.CHEST) || state.isOf(Blocks.TRAPPED_CHEST)) && lastChestSecretTime + 1000 < System.currentTimeMillis() || state.isOf(Blocks.PLAYER_HEAD) || state.isOf(Blocks.PLAYER_WALL_HEAD)) { + secretWaypoints.column(pos).values().stream().filter(SecretWaypoint::needsInteraction).findAny() + .ifPresent(secretWaypoint -> markSecretsFoundAndLogInfo(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} interaction, setting secret #{} as found", secretWaypoint.category, secretWaypoint.secretIndex)); + if (state.isOf(Blocks.CHEST) || state.isOf(Blocks.TRAPPED_CHEST)) { + lastChestSecret = pos; + lastChestSecretTime = System.currentTimeMillis(); + } } else if (state.isOf(Blocks.LEVER)) { - secretWaypoints.column(hitResult.getBlockPos()).values().stream().filter(SecretWaypoint::isLever).forEach(SecretWaypoint::setFound); + secretWaypoints.column(pos).values().stream().filter(SecretWaypoint::isLever).forEach(SecretWaypoint::setFound); } } /** - * Marks the closest secret that requires item pickup no greater than 6 blocks away as found when the player picks up a secret item. + * Marks the closest secret that requires item pickup no greater than 6 blocks away as found when a secret item is removed from the world. * * @param itemEntity the item entity being picked up - * @param collector the collector of the item - * @see #onSecretFound(SecretWaypoint, String, Object...) + * @see #markSecretsFoundAndLogInfo(SecretWaypoint, String, Object...) */ - protected void onItemPickup(ItemEntity itemEntity, LivingEntity collector) { + protected void onItemPickup(ItemEntity itemEntity) { if (SecretWaypoint.SECRET_ITEMS.stream().noneMatch(itemEntity.getStack().getName().getString()::contains)) { return; } - secretWaypoints.values().stream().filter(SecretWaypoint::needsItemPickup).min(Comparator.comparingDouble(SecretWaypoint.getSquaredDistanceToFunction(collector))).filter(SecretWaypoint.getRangePredicate(collector)) - .ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} picked up a {} from a {} secret, setting secret #{} as found", collector.getName().getString(), itemEntity.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex)); + secretWaypoints.values().stream().filter(SecretWaypoint::needsItemPickup).min(Comparator.comparingDouble(SecretWaypoint.getSquaredDistanceToFunction(itemEntity))).filter(SecretWaypoint.getRangePredicate(itemEntity)) + .ifPresent(secretWaypoint -> markSecretsFoundAndLogInfo(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected item {} removed from a {} secret, setting secret #{} as found", itemEntity.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex)); } /** * Marks the closest bat secret as found when a bat is killed. * * @param bat the bat being killed - * @see #onSecretFound(SecretWaypoint, String, Object...) + * @see #markSecretsFoundAndLogInfo(SecretWaypoint, String, Object...) */ protected void onBatRemoved(AmbientEntity bat) { secretWaypoints.values().stream().filter(SecretWaypoint::isBat).min(Comparator.comparingDouble(SecretWaypoint.getSquaredDistanceToFunction(bat))) - .ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} killed for a {} secret, setting secret #{} as found", bat.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex)); + .ifPresent(secretWaypoint -> markSecretsFoundAndLogInfo(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} killed for a {} secret, setting secret #{} as found", bat.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex)); } /** - * Marks all secret waypoints with the same index as the given {@link SecretWaypoint} as found. + * Marks all secret waypoints with the same index as the given {@link SecretWaypoint} as found and logs the given message. * * @param secretWaypoint the secret waypoint to read the index from. * @param msg the message to log * @param args the args for the {@link org.slf4j.Logger#info(String, Object...) Logger#info(String, Object...)} call */ - private void onSecretFound(SecretWaypoint secretWaypoint, String msg, Object... args) { - secretWaypoints.row(secretWaypoint.secretIndex).values().forEach(SecretWaypoint::setFound); + private void markSecretsFoundAndLogInfo(SecretWaypoint secretWaypoint, String msg, Object... args) { + markSecretsAndLogInfo(secretWaypoint, true, msg, args); + } + + /** + * Marks all secret waypoints with the same index as the given {@link SecretWaypoint} as found or missing and logs the given message. + * @param secretWaypoint the secret waypoint to read the index from. + * @param found whether to mark the secret as found or missing + * @param msg the message to log + * @param args the args for the {@link org.slf4j.Logger#info(String, Object...) Logger#info(String, Object...)} call + */ + private void markSecretsAndLogInfo(SecretWaypoint secretWaypoint, boolean found, String msg, Object... args) { + markSecrets(secretWaypoint.secretIndex, found); DungeonManager.LOGGER.info(msg, args); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java index 7b15c61e..79e81ad0 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java @@ -4,7 +4,6 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.Scheduler; -import it.unimi.dsi.fastutil.ints.IntIntPair; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; @@ -14,19 +13,18 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RotationAxis; +import org.joml.Vector2i; +import org.joml.Vector2ic; import java.awt.*; -import java.util.Arrays; +import java.util.List; import java.util.Map; -import org.joml.Vector2i; -import org.joml.Vector2ic; - public class CrystalsHud { private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); protected static final Identifier MAP_TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/crystals_map.png"); private static final Identifier MAP_ICON = new Identifier("textures/map/map_icons.png"); - private static final String[] SMALL_LOCATIONS = { "Fairy Grotto", "King Yolkar", "Corleone", "Odawa", "Key Guardian" }; + private static final List<String> SMALL_LOCATIONS = List.of("Fairy Grotto", "King Yolkar", "Corleone", "Odawa", "Key Guardian"); public static boolean visible = false; @@ -47,9 +45,8 @@ public class CrystalsHud { }); } - protected static IntIntPair getDimensionsForConfig() { - int size = (int) (62 * SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.mapScaling); - return IntIntPair.of(size, size); + protected static int getDimensionsForConfig() { + return (int) (62 * SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.mapScaling); } @@ -83,8 +80,8 @@ public class CrystalsHud { Vector2ic renderPos = transformLocation(waypoint.pos.getX(), waypoint.pos.getZ()); int locationSize = SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.locationSize; - if (Arrays.asList(SMALL_LOCATIONS).contains(waypoint.name.getString())) {//if small location half the location size - locationSize = locationSize / 2; + if (SMALL_LOCATIONS.contains(waypoint.name.getString())) {//if small location half the location size + locationSize /= 2; } //fill square of size locationSize around the coordinates of the location @@ -119,7 +116,7 @@ public class CrystalsHud { } /** - * Converts an X and Z coordinate in the crystal hollow to a X and Y coordinate on the map. + * Converts an X and Z coordinate in the crystal hollow to an X and Y coordinate on the map. * * @param x the world X coordinate * @param z the world Z coordinate @@ -142,8 +139,8 @@ public class CrystalsHud { * Based off code from {@link net.minecraft.client.render.MapRenderer} */ private static float yaw2Cardinal(float yaw) { - yaw += + 180; //flip direction - byte clipped = (byte) ((yaw += yaw < 0.0 ? -8.0 : 8.0) * 16.0 / 360.0); + yaw += 180; //flip direction + byte clipped = (byte) ((yaw + (yaw < 0.0 ? -8.0 : 8.0)) * 16.0 / 360.0); return (clipped * 360f) / 16f; } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHudConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHudConfigScreen.java index b4e423e9..15e605b9 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHudConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHudConfigScreen.java @@ -1,69 +1,44 @@ package de.hysky.skyblocker.skyblock.dwarven; -import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.utils.render.RenderHelper; -import it.unimi.dsi.fastutil.ints.IntIntPair; +import de.hysky.skyblocker.config.HudConfigScreen; +import de.hysky.skyblocker.config.SkyblockerConfig; +import de.hysky.skyblocker.skyblock.tabhud.widget.EmptyWidget; +import de.hysky.skyblocker.skyblock.tabhud.widget.Widget; +import it.unimi.dsi.fastutil.ints.IntIntMutablePair; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; -import java.awt.*; +import java.util.List; -public class CrystalsHudConfigScreen extends Screen { - - private int hudX = SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.x; - private int hudY = SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.y; - private final Screen parent; +public class CrystalsHudConfigScreen extends HudConfigScreen { + private static final EmptyWidget WIDGET = new EmptyWidget(); protected CrystalsHudConfigScreen() { this(null); } public CrystalsHudConfigScreen(Screen parent) { - super(Text.of("Crystals HUD Config")); - this.parent = parent; - } - - @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); - renderBackground(context, mouseX, mouseY, delta); - renderHUDMap(context, hudX, hudY); - context.drawCenteredTextWithShadow(textRenderer, "Right Click To Reset Position", width / 2, height / 2, Color.GRAY.getRGB()); + super(Text.of("Crystals HUD Config"), parent, WIDGET); + WIDGET.setDimensions(CrystalsHud.getDimensionsForConfig()); } + @SuppressWarnings("SuspiciousNameCombination") @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - IntIntPair dims = CrystalsHud.getDimensionsForConfig(); - if (RenderHelper.pointIsInArea(mouseX, mouseY, hudX, hudY, hudX + dims.leftInt(), hudY + dims.rightInt()) && button == 0) { - hudX = (int) Math.max(Math.min(mouseX - (double) dims.leftInt() / 2, this.width - dims.leftInt()), 0); - hudY = (int) Math.max(Math.min(mouseY - (double) dims.rightInt() / 2, this.height - dims.rightInt()), 0); - } - return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + protected List<IntIntMutablePair> getConfigPos(SkyblockerConfig config) { + return List.of(IntIntMutablePair.of(config.locations.dwarvenMines.crystalsHud.x, config.locations.dwarvenMines.crystalsHud.y)); } @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (button == 1) { - IntIntPair dims = CrystalsHud.getDimensionsForConfig(); - hudX = this.width / 2 - dims.leftInt(); - hudY = this.height / 2 - dims.rightInt(); - } - return super.mouseClicked(mouseX, mouseY, button); + protected void renderWidget(DrawContext context, List<Widget> widgets) { + int size = CrystalsHud.getDimensionsForConfig(); + WIDGET.setDimensions(size); + context.drawTexture(CrystalsHud.MAP_TEXTURE, WIDGET.getX(), WIDGET.getY(), 0, 0, size, size, size, size); } - private void renderHUDMap(DrawContext context, int x, int y) { - float scaling = SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.mapScaling; - int size = (int) (62 * scaling); - context.drawTexture(CrystalsHud.MAP_TEXTURE, x, y, 0, 0, size, size, size, size); - } - @Override - public void close() { - SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.x = hudX; - SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.y = hudY; - SkyblockerConfigManager.save(); - - client.setScreen(parent); + protected void savePos(SkyblockerConfig configManager, List<Widget> widgets) { + configManager.locations.dwarvenMines.crystalsHud.x = widgets.get(0).getX(); + configManager.locations.dwarvenMines.crystalsHud.y = widgets.get(0).getY(); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java index 0a4e4518..f43574ab 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java @@ -9,6 +9,7 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Constants; import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.scheduler.Scheduler; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; @@ -47,12 +48,13 @@ public class CrystalsLocationsManager { /** * A look-up table to convert between location names and waypoint in the {@link CrystalsWaypoint.Category} values. */ - protected static final Map<String, CrystalsWaypoint.Category> WAYPOINT_LOCATIONS = Arrays.stream(CrystalsWaypoint.Category.values()).collect(Collectors.toMap(CrystalsWaypoint.Category::toString, Function.identity())); + private static final Map<String, CrystalsWaypoint.Category> WAYPOINT_LOCATIONS = Arrays.stream(CrystalsWaypoint.Category.values()).collect(Collectors.toMap(CrystalsWaypoint.Category::toString, Function.identity())); private static final Pattern TEXT_CWORDS_PATTERN = Pattern.compile("([0-9][0-9][0-9]) ([0-9][0-9][0-9]?) ([0-9][0-9][0-9])"); protected static Map<String, CrystalsWaypoint> activeWaypoints = new HashMap<>(); public static void init() { + Scheduler.INSTANCE.scheduleCyclic(CrystalsLocationsManager::update, 40); WorldRenderEvents.AFTER_TRANSLUCENT.register(CrystalsLocationsManager::render); ClientReceiveMessageEvents.GAME.register(CrystalsLocationsManager::extractLocationFromMessage); ClientCommandRegistrationCallback.EVENT.register(CrystalsLocationsManager::registerWaypointLocationCommands); @@ -83,7 +85,7 @@ public class CrystalsLocationsManager { for (String waypointLocation : WAYPOINT_LOCATIONS.keySet()) { if (value.toLowerCase().contains(waypointLocation.toLowerCase())) { //todo be more lenient //all data found to create waypoint - addCustomWaypoint(Text.of(waypointLocation),blockPos); + addCustomWaypoint(waypointLocation, blockPos); return; } } @@ -144,7 +146,7 @@ public class CrystalsLocationsManager { BlockPos blockPos = location.toAbsoluteBlockPos(new ServerCommandSource(null, source.getPosition(), source.getRotation(), null, 0, null, null, null, null)); if (WAYPOINT_LOCATIONS.containsKey(place)) { - addCustomWaypoint(Text.of(place), blockPos); + addCustomWaypoint(place, blockPos); //tell the client it has done this if (CLIENT.player == null || CLIENT.getNetworkHandler() == null) { @@ -158,10 +160,10 @@ public class CrystalsLocationsManager { } - private static void addCustomWaypoint( Text waypointName, BlockPos pos) { - CrystalsWaypoint.Category category = WAYPOINT_LOCATIONS.get(waypointName.getString()); - CrystalsWaypoint waypoint = new CrystalsWaypoint(category, waypointName, pos); - activeWaypoints.put(waypointName.getString(), waypoint); + private static void addCustomWaypoint(String waypointName, BlockPos pos) { + CrystalsWaypoint.Category category = WAYPOINT_LOCATIONS.get(waypointName); + CrystalsWaypoint waypoint = new CrystalsWaypoint(category, Text.literal(waypointName), pos); + activeWaypoints.put(waypointName, waypoint); } public static void render(WorldRenderContext context) { @@ -184,12 +186,12 @@ public class CrystalsLocationsManager { } //get if the player is in the crystals - String location = Utils.getIslandArea().replace("⏣ ", ""); + String location = Utils.getIslandArea().substring(2); //if new location and needs waypoint add waypoint if (!location.equals("Unknown") && WAYPOINT_LOCATIONS.containsKey(location) && !activeWaypoints.containsKey(location)) { //add waypoint at player location BlockPos playerLocation = CLIENT.player.getBlockPos(); - addCustomWaypoint(Text.of(location), playerLocation); + addCustomWaypoint(location, playerLocation); } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java index 608873c0..58abd980 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java @@ -6,13 +6,12 @@ import de.hysky.skyblocker.skyblock.tabhud.widget.hud.HudCommsWidget; import de.hysky.skyblocker.skyblock.tabhud.widget.hud.HudPowderWidget; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.scheduler.Scheduler; -import it.unimi.dsi.fastutil.Pair; -import it.unimi.dsi.fastutil.ints.IntIntPair; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.network.PlayerListEntry; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -44,7 +43,7 @@ public class DwarvenHud { "First Event", "(?:Ruby|Amber|Sapphire|Jade|Amethyst|Topaz) Gemstone Collector", "(?:Amber|Sapphire|Jade|Amethyst|Topaz) Crystal Hunter", - "Chest Looter").map(s -> Pattern.compile("^.*(" + s + "): (\\d+\\.?\\d*%|DONE)")) + "Chest Looter").map(s -> Pattern.compile("(" + s + "): (\\d+\\.?\\d*%|DONE)")) .collect(Collectors.toList()); public static final Pattern MITHRIL_PATTERN = Pattern.compile("Mithril Powder: [0-9,]+"); public static final Pattern GEMSTONE_PATTERN = Pattern.compile("Gemstone Powder: [0-9,]+"); @@ -56,7 +55,7 @@ public class DwarvenHud { .executes(Scheduler.queueOpenScreenCommand(DwarvenHudConfigScreen::new)))))); HudRenderCallback.EVENT.register((context, tickDelta) -> { - if ((!SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledCommissions && !SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) + if ((!SkyblockerConfigManager.get().general.tabHud.enableHudBackground && !SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) || client.options.playerListKey.isPressed() || client.player == null || (!Utils.isInDwarvenMines() && !Utils.isInCrystalHollows())) { @@ -72,52 +71,11 @@ public class DwarvenHud { }); } - /** - * Gets the dimensions (width, height) for the commissions hud and the powder hud - * @param commissions what commissions to get the dimensions for - * @return a {@link Pair} of {@link IntIntPair} with the first pair being for the commissions hud and the second pair being for the powder hud - */ - public static Pair<IntIntPair,IntIntPair> getDimForConfig(List<Commission> commissions) { - return switch (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.style) { - case SIMPLE -> { - HudCommsWidget.INSTANCE_CFG.updateData(commissions, false); - yield Pair.of( - IntIntPair.of( - HudCommsWidget.INSTANCE_CFG.getWidth(), - HudCommsWidget.INSTANCE_CFG.getHeight()), - IntIntPair.of( - HudPowderWidget.INSTANCE_CFG.getWidth(), - HudPowderWidget.INSTANCE_CFG.getHeight()) - ); - } - case FANCY -> { - HudCommsWidget.INSTANCE_CFG.updateData(commissions, true); - yield Pair.of( - IntIntPair.of( - HudCommsWidget.INSTANCE_CFG.getWidth(), - HudCommsWidget.INSTANCE_CFG.getHeight()), - IntIntPair.of( - HudPowderWidget.INSTANCE_CFG.getWidth(), - HudPowderWidget.INSTANCE_CFG.getHeight()) - ); - } - default -> Pair.of( - IntIntPair.of( - 200, - 20 * commissions.size()), - IntIntPair.of( - 200, - 40) - ); - }; - } - public static void render(HudCommsWidget hcw, HudPowderWidget hpw, DrawContext context, int comHudX, int comHudY, int powderHudX, int powderHudY, List<Commission> commissions) { - switch (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.style) { - case SIMPLE -> renderSimple(hcw,hpw, context, comHudX, comHudY,powderHudX,powderHudY, commissions); - case FANCY -> renderFancy(hcw,hpw, context, comHudX, comHudY,powderHudX,powderHudY, commissions); - case CLASSIC -> renderClassic(context, comHudX, comHudY,powderHudX,powderHudY, commissions); + case SIMPLE -> renderSimple(hcw, hpw, context, comHudX, comHudY, powderHudX, powderHudY, commissions); + case FANCY -> renderFancy(hcw, hpw, context, comHudX, comHudY, powderHudX, powderHudY, commissions); + case CLASSIC -> renderClassic(context, comHudX, comHudY, powderHudX, powderHudY, commissions); } } @@ -131,11 +89,11 @@ public class DwarvenHud { * @param commissions the commissions to render to the commissions hud */ public static void renderClassic(DrawContext context, int comHudX, int comHudY, int powderHudX, int powderHudY, List<Commission> commissions) { - if (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground) { + if (SkyblockerConfigManager.get().general.tabHud.enableHudBackground) { context.fill(comHudX, comHudY, comHudX + 200, comHudY + (20 * commissions.size()), 0x64000000); context.fill(powderHudX, powderHudY, powderHudX + 200, powderHudY + 40, 0x64000000); } - if (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledCommissions) { + if (SkyblockerConfigManager.get().general.tabHud.enableHudBackground) { int y = 0; for (Commission commission : commissions) { float percentage; @@ -167,69 +125,68 @@ public class DwarvenHud { } public static void renderSimple(HudCommsWidget hcw, HudPowderWidget hpw, DrawContext context, int comHudX, int comHudY, int powderHudX, int powderHudY, List<Commission> commissions) { - if (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledCommissions) { + if (SkyblockerConfigManager.get().general.tabHud.enableHudBackground) { hcw.updateData(commissions, false); hcw.update(); hcw.setX(comHudX); hcw.setY(comHudY); - hcw.render(context, - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + hcw.render(context, SkyblockerConfigManager.get().general.tabHud.enableHudBackground); } if (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) { hpw.update(); hpw.setX(powderHudX); hpw.setY(powderHudY); - hpw.render(context, - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + hpw.render(context, SkyblockerConfigManager.get().general.tabHud.enableHudBackground); } } public static void renderFancy(HudCommsWidget hcw, HudPowderWidget hpw, DrawContext context, int comHudX, int comHudY, int powderHudX, int powderHudY, List<Commission> commissions) { - if (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledCommissions) { + if (SkyblockerConfigManager.get().general.tabHud.enableHudBackground) { hcw.updateData(commissions, true); hcw.update(); hcw.setX(comHudX); hcw.setY(comHudY); hcw.render(context, - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + SkyblockerConfigManager.get().general.tabHud.enableHudBackground); } if (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) { hpw.update(); hpw.setX(powderHudX); hpw.setY(powderHudY); hpw.render(context, - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + SkyblockerConfigManager.get().general.tabHud.enableHudBackground); } } public static void update() { - if (client.player == null || client.getNetworkHandler() == null || (!SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledCommissions && !SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) + if (client.player == null || client.getNetworkHandler() == null || (!SkyblockerConfigManager.get().general.tabHud.enableHudBackground && !SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) || (!Utils.isInCrystalHollows() && !Utils.isInDwarvenMines())) return; commissionList = new ArrayList<>(); - client.getNetworkHandler().getPlayerList().forEach(playerListEntry -> { - if (playerListEntry.getDisplayName() != null) { - //find commissions - for (Pattern pattern : COMMISSIONS) { - Matcher matcher = pattern.matcher(playerListEntry.getDisplayName().getString()); - if (matcher.find()) { - commissionList.add(new Commission(matcher.group(1), matcher.group(2))); - } - - } - //find powder - Matcher mithrilMatcher = MITHRIL_PATTERN.matcher(playerListEntry.getDisplayName().getString()); - if (mithrilMatcher.find()){ - mithrilPowder = mithrilMatcher.group(0).split(": ")[1]; - } - Matcher gemstoneMatcher = GEMSTONE_PATTERN.matcher(playerListEntry.getDisplayName().getString()); - if (gemstoneMatcher.find()){ - gemStonePowder = gemstoneMatcher.group(0).split(": ")[1]; + for (PlayerListEntry playerListEntry : client.getNetworkHandler().getPlayerList()) { + if (playerListEntry.getDisplayName() == null) { + continue; + } + //find commissions + String name = playerListEntry.getDisplayName().getString().strip(); + for (Pattern pattern : COMMISSIONS) { + Matcher matcher = pattern.matcher(name); + if (matcher.matches()) { + commissionList.add(new Commission(matcher.group(1), matcher.group(2))); } } - }); + //find powder + Matcher mithrilMatcher = MITHRIL_PATTERN.matcher(name); + if (mithrilMatcher.matches()) { + mithrilPowder = mithrilMatcher.group(0).split(": ")[1]; + } + Matcher gemstoneMatcher = GEMSTONE_PATTERN.matcher(name); + if (gemstoneMatcher.matches()) { + gemStonePowder = gemstoneMatcher.group(0).split(": ")[1]; + } + } } // steamroller tactics to get visibility from outside classes (HudCommsWidget) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java index d5dc19f2..79a139f9 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java @@ -1,80 +1,55 @@ package de.hysky.skyblocker.skyblock.dwarven; +import de.hysky.skyblocker.config.HudConfigScreen; +import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.dwarven.DwarvenHud.Commission; +import de.hysky.skyblocker.skyblock.tabhud.widget.Widget; import de.hysky.skyblocker.skyblock.tabhud.widget.hud.HudCommsWidget; import de.hysky.skyblocker.skyblock.tabhud.widget.hud.HudPowderWidget; -import de.hysky.skyblocker.utils.render.RenderHelper; -import it.unimi.dsi.fastutil.Pair; -import it.unimi.dsi.fastutil.ints.IntIntPair; +import it.unimi.dsi.fastutil.ints.IntIntMutablePair; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; -import java.awt.*; import java.util.List; -public class DwarvenHudConfigScreen extends Screen { - +public class DwarvenHudConfigScreen extends HudConfigScreen { private static final List<DwarvenHud.Commission> CFG_COMMS = List.of(new Commission("Test Commission 1", "1%"), new DwarvenHud.Commission("Test Commission 2", "2%")); - private int commissionsHudX = SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.x; - private int commissionsHudY = SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.y; - - private int powderHudX = SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.powderX; - private int powderHudY = SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.powderY; - private final Screen parent; protected DwarvenHudConfigScreen() { this(null); } public DwarvenHudConfigScreen(Screen parent) { - super(Text.of("Dwarven HUD Config")); - this.parent = parent; - } - - @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); - renderBackground(context, mouseX, mouseY, delta); - DwarvenHud.render(HudCommsWidget.INSTANCE_CFG, HudPowderWidget.INSTANCE_CFG, context, commissionsHudX, commissionsHudY, powderHudX, powderHudY, CFG_COMMS); - context.drawCenteredTextWithShadow(textRenderer, "Right Click To Reset Position", width / 2, height / 2, Color.GRAY.getRGB()); + super(Text.literal("Dwarven HUD Config"), parent, List.of(HudCommsWidget.INSTANCE_CFG, HudPowderWidget.INSTANCE_CFG)); + if (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.style == SkyblockerConfig.DwarvenHudStyle.CLASSIC) { + HudCommsWidget.INSTANCE_CFG.setWidth(200); + HudCommsWidget.INSTANCE_CFG.setHeight(20 * CFG_COMMS.size()); + HudPowderWidget.INSTANCE_CFG.setWidth(200); + HudPowderWidget.INSTANCE_CFG.setHeight(40); + } } + @SuppressWarnings("SuspiciousNameCombination") @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - Pair<IntIntPair,IntIntPair> dims = DwarvenHud.getDimForConfig(CFG_COMMS); - if (RenderHelper.pointIsInArea(mouseX, mouseY, commissionsHudX, commissionsHudY, commissionsHudX + 200, commissionsHudY + 40) && button == 0) { - commissionsHudX = (int) Math.max(Math.min(mouseX - (double) dims.first().leftInt() / 2, this.width - dims.first().leftInt()), 0); - commissionsHudY = (int) Math.max(Math.min(mouseY - (double) dims.first().rightInt() / 2, this.height - dims.first().rightInt()), 0); - } - if (RenderHelper.pointIsInArea(mouseX, mouseY, powderHudX, powderHudY, powderHudX + 200, powderHudY + 40) && button == 0) { - powderHudX = (int) Math.max(Math.min(mouseX - (double) dims.second().leftInt() / 2, this.width - dims.second().leftInt()), 0); - powderHudY = (int) Math.max(Math.min(mouseY - (double) dims.second().rightInt() / 2, this.height - dims.second().rightInt()), 0); - } - return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + protected List<IntIntMutablePair> getConfigPos(SkyblockerConfig config) { + return List.of( + IntIntMutablePair.of(config.locations.dwarvenMines.dwarvenHud.x, config.locations.dwarvenMines.dwarvenHud.y), + IntIntMutablePair.of(config.locations.dwarvenMines.dwarvenHud.powderX, config.locations.dwarvenMines.dwarvenHud.powderY) + ); } @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (button == 1) { - Pair<IntIntPair,IntIntPair> dims = DwarvenHud.getDimForConfig(CFG_COMMS); - commissionsHudX = this.width / 2 - dims.left().leftInt(); - commissionsHudY = this.height / 2 - dims.left().rightInt(); - powderHudX = this.width / 2 - dims.right().leftInt(); - powderHudY = this.height / 2 - dims.right().rightInt() + dims.left().rightInt(); //add this to make it bellow the other widget - } - return super.mouseClicked(mouseX, mouseY, button); + protected void renderWidget(DrawContext context, List<Widget> widgets) { + DwarvenHud.render(HudCommsWidget.INSTANCE_CFG, HudPowderWidget.INSTANCE_CFG, context, widgets.get(0).getX(), widgets.get(0).getY(), widgets.get(1).getX(), widgets.get(1).getY(), CFG_COMMS); } @Override - public void close() { - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.x = commissionsHudX; - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.y = commissionsHudY; - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.powderX = powderHudX; - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.powderY = powderHudY; - SkyblockerConfigManager.save(); - - client.setScreen(parent); + protected void savePos(SkyblockerConfig configManager, List<Widget> widgets) { + configManager.locations.dwarvenMines.dwarvenHud.x = widgets.get(0).getX(); + configManager.locations.dwarvenMines.dwarvenHud.y = widgets.get(0).getY(); + configManager.locations.dwarvenMines.dwarvenHud.powderX = widgets.get(1).getX(); + configManager.locations.dwarvenMines.dwarvenHud.powderY = widgets.get(1).getY(); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/end/BeaconHighlighter.java b/src/main/java/de/hysky/skyblocker/skyblock/end/BeaconHighlighter.java index 6c89a07c..a2298ecf 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/end/BeaconHighlighter.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/end/BeaconHighlighter.java @@ -48,7 +48,7 @@ public class BeaconHighlighter { private static void render(WorldRenderContext context) { if (Utils.isInTheEnd() && SkyblockerConfigManager.get().slayer.endermanSlayer.highlightBeacons) { for (BlockPos pos : beaconPositions) { - RenderHelper.renderFilled(context, pos, RED_COLOR_COMPONENTS, 0.5f, false); + RenderHelper.renderFilled(context, pos, RED_COLOR_COMPONENTS, 0.5f, true); } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudConfigScreen.java index 2502afd7..659fc79f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudConfigScreen.java @@ -2,34 +2,27 @@ package de.hysky.skyblocker.skyblock.end; import de.hysky.skyblocker.config.HudConfigScreen; import de.hysky.skyblocker.config.SkyblockerConfig; -import de.hysky.skyblocker.config.SkyblockerConfigManager; -import net.minecraft.client.gui.DrawContext; +import de.hysky.skyblocker.skyblock.tabhud.widget.Widget; +import it.unimi.dsi.fastutil.ints.IntIntMutablePair; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; +import java.util.List; + public class EndHudConfigScreen extends HudConfigScreen { public EndHudConfigScreen(Screen parent) { - super(Text.literal("End HUD Config"), EndHudWidget.INSTANCE, parent); - } - - @Override - protected int[] getPosFromConfig(SkyblockerConfig config) { - return new int[]{ - config.locations.end.x, - config.locations.end.y, - }; + super(Text.literal("End HUD Config"), parent, EndHudWidget.INSTANCE); } + @SuppressWarnings("SuspiciousNameCombination") @Override - protected void savePos(SkyblockerConfig configManager, int x, int y) { - configManager.locations.end.x = x; - configManager.locations.end.y = y; + protected List<IntIntMutablePair> getConfigPos(SkyblockerConfig config) { + return List.of(IntIntMutablePair.of(config.locations.end.x, config.locations.end.y)); } @Override - protected void renderWidget(DrawContext context, int x, int y) { - EndHudWidget.INSTANCE.setX(x); - EndHudWidget.INSTANCE.setY(y); - EndHudWidget.INSTANCE.render(context, SkyblockerConfigManager.get().locations.end.enableBackground); + protected void savePos(SkyblockerConfig configManager, List<Widget> widgets) { + configManager.locations.end.x = widgets.get(0).getX(); + configManager.locations.end.y = widgets.get(0).getY(); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java b/src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java index 1db27769..10672bde 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java @@ -76,7 +76,7 @@ public class TheEnd { if (!Utils.isInTheEnd()) return; if (!SkyblockerConfigManager.get().locations.end.hudEnabled) return; - EndHudWidget.INSTANCE.render(drawContext, SkyblockerConfigManager.get().locations.end.enableBackground); + EndHudWidget.INSTANCE.render(drawContext, SkyblockerConfigManager.get().general.tabHud.enableHudBackground); }); ClientChunkEvents.CHUNK_LOAD.register((world, chunk) -> { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java index 90513a4b..85b41bd2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java @@ -44,7 +44,7 @@ public class MobGlow { // Regular Mobs if (!(entity instanceof ArmorStandEntity)) { - List<ArmorStandEntity> armorStands = getArmorStands(entity.getWorld(), box); + List<ArmorStandEntity> armorStands = getArmorStands(entity); if (!armorStands.isEmpty() && armorStands.get(0).getName().getString().contains("✯")) return SkyblockerConfigManager.get().locations.dungeons.starredMobGlow; @@ -79,7 +79,11 @@ public class MobGlow { return false; } - private static List<ArmorStandEntity> getArmorStands(World world, Box box) { + public static List<ArmorStandEntity> getArmorStands(Entity entity) { + return getArmorStands(entity.getWorld(), entity.getBoundingBox()); + } + + public static List<ArmorStandEntity> getArmorStands(World world, Box box) { return world.getEntitiesByClass(ArmorStandEntity.class, box.expand(0, 2, 0), EntityPredicates.NOT_MOUNTED); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java new file mode 100644 index 00000000..95c72241 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java @@ -0,0 +1,123 @@ +package de.hysky.skyblocker.skyblock.garden; + +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.utils.ItemUtils; +import de.hysky.skyblocker.utils.Location; +import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.scheduler.Scheduler; +import it.unimi.dsi.fastutil.floats.FloatLongPair; +import it.unimi.dsi.fastutil.ints.IntLongPair; +import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue; +import it.unimi.dsi.fastutil.longs.LongPriorityQueue; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; +import net.fabricmc.fabric.api.event.client.player.ClientPlayerBlockBreakEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.item.ItemStack; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Locale; +import java.util.Queue; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; + +public class FarmingHud { + private static final Logger LOGGER = LoggerFactory.getLogger(FarmingHud.class); + public static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance(Locale.US); + private static final Pattern COUNTER = Pattern.compile("Counter: (?<count>[\\d,]+) .+"); + private static final Pattern FARMING_XP = Pattern.compile("§3\\+(?<xp>\\d+.?\\d*) Farming \\((?<percent>\\d+.?\\d*)%\\)"); + private static final Deque<IntLongPair> counter = new ArrayDeque<>(); + private static final LongPriorityQueue blockBreaks = new LongArrayFIFOQueue(); + private static final Queue<FloatLongPair> farmingXp = new ArrayDeque<>(); + private static float farmingXpPercentProgress; + + public static void init() { + HudRenderCallback.EVENT.register((context, tickDelta) -> { + if (shouldRender()) { + if (!counter.isEmpty() && counter.peek().rightLong() + 10_000 < System.currentTimeMillis()) { + counter.poll(); + } + if (!blockBreaks.isEmpty() && blockBreaks.firstLong() + 1000 < System.currentTimeMillis()) { + blockBreaks.dequeueLong(); + } + if (!farmingXp.isEmpty() && farmingXp.peek().rightLong() + 1000 < System.currentTimeMillis()) { + farmingXp.poll(); + } + + ItemStack stack = MinecraftClient.getInstance().player.getMainHandStack(); + Matcher matcher = ItemUtils.getNbtTooltip(stack, FarmingHud.COUNTER); + if (matcher != null) { + try { + int count = NUMBER_FORMAT.parse(matcher.group("count")).intValue(); + if (counter.isEmpty() || counter.peekLast().leftInt() != count) { + counter.offer(IntLongPair.of(count, System.currentTimeMillis())); + } + } catch (ParseException e) { + LOGGER.error("[Skyblocker Farming HUD] Failed to parse counter", e); + } + } + + FarmingHudWidget.INSTANCE.update(); + FarmingHudWidget.INSTANCE.render(context, SkyblockerConfigManager.get().general.tabHud.enableHudBackground); + } + }); + ClientPlayerBlockBreakEvents.AFTER.register((world, player, pos, state) -> { + if (shouldRender()) { + blockBreaks.enqueue(System.currentTimeMillis()); + } + }); + ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + if (shouldRender() && overlay) { + Matcher matcher = FARMING_XP.matcher(message.getString()); + if (matcher.matches()) { + try { + farmingXp.offer(FloatLongPair.of(NUMBER_FORMAT.parse(matcher.group("xp")).floatValue(), System.currentTimeMillis())); + farmingXpPercentProgress = NUMBER_FORMAT.parse(matcher.group("percent")).floatValue(); + } catch (ParseException e) { + LOGGER.error("[Skyblocker Farming HUD] Failed to parse farming xp", e); + } + } + } + }); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE).then(literal("hud").then(literal("farming") + .executes(Scheduler.queueOpenScreenCommand(() -> new FarmingHudConfigScreen(null))))))); + } + + private static boolean shouldRender() { + return SkyblockerConfigManager.get().locations.garden.farmingHud.enableHud && Utils.getLocation() == Location.GARDEN; + } + + public static int counter() { + return counter.isEmpty() ? 0 : counter.peekLast().leftInt(); + } + + public static float cropsPerMinute() { + if (counter.isEmpty()) { + return 0; + } + IntLongPair first = counter.peek(); + IntLongPair last = counter.peekLast(); + return (float) (last.leftInt() - first.leftInt()) / (last.rightLong() - first.rightLong()) * 60_000f; + } + + public static int blockBreaks() { + return blockBreaks.size(); + } + + public static float farmingXpPercentProgress() { + return farmingXpPercentProgress; + } + + public static double farmingXpPerHour() { + return farmingXp.stream().mapToDouble(FloatLongPair::leftFloat).sum() * 3600; + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudConfigScreen.java new file mode 100644 index 00000000..5384d47a --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudConfigScreen.java @@ -0,0 +1,30 @@ +package de.hysky.skyblocker.skyblock.garden; + +import de.hysky.skyblocker.config.HudConfigScreen; +import de.hysky.skyblocker.config.SkyblockerConfig; +import de.hysky.skyblocker.skyblock.tabhud.widget.Widget; +import it.unimi.dsi.fastutil.ints.IntIntMutablePair; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; + +import java.util.List; + +public class FarmingHudConfigScreen extends HudConfigScreen { + public FarmingHudConfigScreen(Screen parent) { + super(Text.literal("Farming HUD Config"), parent, FarmingHudWidget.INSTANCE); + } + + @SuppressWarnings("SuspiciousNameCombination") + @Override + protected List<IntIntMutablePair> getConfigPos(SkyblockerConfig config) { + return List.of( + IntIntMutablePair.of(config.locations.garden.farmingHud.x, config.locations.garden.farmingHud.y) + ); + } + + @Override + protected void savePos(SkyblockerConfig configManager, List<Widget> widgets) { + configManager.locations.garden.farmingHud.x = widgets.get(0).getX(); + configManager.locations.garden.farmingHud.y = widgets.get(0).getY(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudWidget.java new file mode 100644 index 00000000..6ddb0e05 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHudWidget.java @@ -0,0 +1,67 @@ +package de.hysky.skyblocker.skyblock.garden; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.tabhud.util.Ico; +import de.hysky.skyblocker.skyblock.tabhud.widget.Widget; +import de.hysky.skyblocker.skyblock.tabhud.widget.component.PlainTextComponent; +import de.hysky.skyblocker.skyblock.tabhud.widget.component.ProgressComponent; +import de.hysky.skyblocker.utils.ItemUtils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.item.ItemStack; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.MathHelper; + +import java.util.Map; + +public class FarmingHudWidget extends Widget { + private static final MutableText TITLE = Text.literal("Farming").formatted(Formatting.YELLOW, Formatting.BOLD); + private static final Map<String, ItemStack> FARMING_TOOLS = Map.ofEntries( + Map.entry("THEORETICAL_HOE_WHEAT_1", Ico.WHEAT), + Map.entry("THEORETICAL_HOE_WHEAT_2", Ico.WHEAT), + Map.entry("THEORETICAL_HOE_WHEAT_3", Ico.WHEAT), + Map.entry("THEORETICAL_HOE_CARROT_1", Ico.CARROT), + Map.entry("THEORETICAL_HOE_CARROT_2", Ico.CARROT), + Map.entry("THEORETICAL_HOE_CARROT_3", Ico.CARROT), + Map.entry("THEORETICAL_HOE_POTATO_1", Ico.POTATO), + Map.entry("THEORETICAL_HOE_POTATO_2", Ico.POTATO), + Map.entry("THEORETICAL_HOE_POTATO_3", Ico.POTATO), + Map.entry("THEORETICAL_HOE_CANE_1", Ico.SUGAR_CANE), + Map.entry("THEORETICAL_HOE_CANE_2", Ico.SUGAR_CANE), + Map.entry("THEORETICAL_HOE_CANE_3", Ico.SUGAR_CANE), + Map.entry("THEORETICAL_HOE_WARTs_1", Ico.NETHER_WART), + Map.entry("THEORETICAL_HOE_WARTs_2", Ico.NETHER_WART), + Map.entry("THEORETICAL_HOE_WARTs_3", Ico.NETHER_WART), + Map.entry("FUNGI_CUTTER", Ico.MUSHROOM), + Map.entry("CACTUS_KNIFE", Ico.CACTUS), + Map.entry("MELON_DICER", Ico.MELON), + Map.entry("PUMPKIN_DICER", Ico.PUMPKIN), + Map.entry("COCO_CHOPPER", Ico.COCOA_BEANS) + ); + public static final FarmingHudWidget INSTANCE = new FarmingHudWidget(); + private final MinecraftClient client = MinecraftClient.getInstance(); + + public FarmingHudWidget() { + super(TITLE, Formatting.YELLOW.getColorValue()); + setX(SkyblockerConfigManager.get().locations.garden.farmingHud.x); + setY(SkyblockerConfigManager.get().locations.garden.farmingHud.y); + update(); + } + + @SuppressWarnings("DataFlowIssue") + @Override + public void updateContent() { + ItemStack icon = FARMING_TOOLS.getOrDefault(ItemUtils.getItemId(client.player.getMainHandStack()), Ico.HOE); + addSimpleIcoText(icon, "Counter: ", Formatting.YELLOW, FarmingHud.NUMBER_FORMAT.format(FarmingHud.counter())); + addSimpleIcoText(icon, "Crops/min: ", Formatting.YELLOW, FarmingHud.NUMBER_FORMAT.format((int) FarmingHud.cropsPerMinute() / 100 * 100)); + addSimpleIcoText(icon, "Blocks/s: ", Formatting.YELLOW, Integer.toString(FarmingHud.blockBreaks())); + addComponent(new ProgressComponent(Ico.LANTERN, Text.literal("Farming Level: "), FarmingHud.farmingXpPercentProgress(), Formatting.GOLD.getColorValue())); + addSimpleIcoText(Ico.LIME_DYE, "Farming XP/h: ", Formatting.YELLOW, FarmingHud.NUMBER_FORMAT.format((int) FarmingHud.farmingXpPerHour())); + + double yaw = client.getCameraEntity().getYaw(); + double pitch = client.getCameraEntity().getPitch(); + addComponent(new PlainTextComponent(Text.literal("Yaw: " + String.format("%.3f", MathHelper.wrapDegrees(yaw))).formatted(Formatting.YELLOW))); + addComponent(new PlainTextComponent(Text.literal("Pitch: " + String.format("%.3f", MathHelper.wrapDegrees(pitch))).formatted(Formatting.YELLOW))); + } +} 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 92e7e258..bde8b3ea 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import java.text.NumberFormat; import java.util.HashMap; +import java.util.Locale; import java.util.Map; //TODO: check inventory items, sum all repeated items into one @@ -111,7 +112,7 @@ public class VisitorHelper { String itemName = splitItemText[0].trim(); if (itemName.isEmpty()) return; try { - int amount = splitItemText.length == 2 ? NumberFormat.getInstance().parse(splitItemText[1].trim()).intValue() : 1; + int amount = splitItemText.length == 2 ? NumberFormat.getInstance(Locale.US).parse(splitItemText[1].trim()).intValue() : 1; Object2IntMap<String> visitorMap = itemMap.getOrDefault(visitorName, new Object2IntOpenHashMap<>()); visitorMap.putIfAbsent(itemName, amount); itemMap.putIfAbsent(visitorName, visitorMap); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java b/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java index 773f1808..ae908245 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java @@ -1,26 +1,10 @@ package de.hysky.skyblocker.skyblock.item; -import java.io.ByteArrayInputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.lang.reflect.Type; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.util.Base64; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; import com.mojang.util.UndashedUuid; - import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.utils.Http; import de.hysky.skyblocker.utils.Http.ApiResponse; @@ -29,12 +13,21 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.minecraft.client.MinecraftClient; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.NbtList; -import net.minecraft.nbt.NbtTagSizeTracker; -import net.minecraft.util.Util; +import net.minecraft.nbt.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.Base64; +import java.util.Map; +import java.util.concurrent.CompletableFuture; public class MuseumItemCache { private static final Logger LOGGER = LoggerFactory.getLogger(MuseumItemCache.class); @@ -142,9 +135,8 @@ public class MuseumItemCache { public static void tick(String profileId) { if (loaded.isDone()) { String uuid = UndashedUuid.toString(MinecraftClient.getInstance().getSession().getUuidOrNull()); - Object2ObjectOpenHashMap<String, ProfileMuseumData> playerData = MUSEUM_ITEM_CACHE.computeIfAbsent(uuid, uuid1 -> Util.make(new Object2ObjectOpenHashMap<>(), map -> { - map.put(profileId, ProfileMuseumData.EMPTY); - })); + Object2ObjectOpenHashMap<String, ProfileMuseumData> playerData = MUSEUM_ITEM_CACHE.computeIfAbsent(uuid, _uuid -> new Object2ObjectOpenHashMap<>()); + playerData.putIfAbsent(profileId, ProfileMuseumData.EMPTY); if (playerData.get(profileId).stale()) updateData4ProfileMember(uuid, profileId); } 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 af2a062b..37de58e6 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 @@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.Objects; @@ -55,7 +54,6 @@ public class BackpackPreview { } public static void tick() { - Utils.update(); // force update isOnSkyblock to prevent crash on disconnect if (Utils.isOnSkyblock()) { // save all dirty storages saveStorages(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/rift/EnigmaSouls.java b/src/main/java/de/hysky/skyblocker/skyblock/rift/EnigmaSouls.java index aa55a4e3..8d0c30b8 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/rift/EnigmaSouls.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/rift/EnigmaSouls.java @@ -71,7 +71,7 @@ public class EnigmaSouls { try (BufferedReader reader = Files.newBufferedReader(FOUND_SOULS_FILE)) { for (Map.Entry<String, JsonElement> profile : JsonParser.parseReader(reader).getAsJsonObject().asMap().entrySet()) { for (JsonElement foundSoul : profile.getValue().getAsJsonArray().asList()) { - SOUL_WAYPOINTS.get(PosUtils.parsePosString(foundSoul.getAsString())).setFound(); + SOUL_WAYPOINTS.get(PosUtils.parsePosString(foundSoul.getAsString())).setFound(profile.getKey()); } } } catch (NoSuchFileException ignored) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java index 96ab35d5..4872435b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/util/Ico.java @@ -53,12 +53,23 @@ public class Ico { public static final ItemStack COMPOSTER = new ItemStack(Items.COMPOSTER); public static final ItemStack SAPLING = new ItemStack(Items.OAK_SAPLING); public static final ItemStack SEEDS = new ItemStack(Items.WHEAT_SEEDS); + public static final ItemStack WHEAT = new ItemStack(Items.WHEAT); + public static final ItemStack CARROT = new ItemStack(Items.CARROT); + public static final ItemStack POTATO = new ItemStack(Items.POTATO); + public static final ItemStack SUGAR_CANE = new ItemStack(Items.SUGAR_CANE); + public static final ItemStack NETHER_WART = new ItemStack(Items.NETHER_WART); + public static final ItemStack MUSHROOM = new ItemStack(Items.RED_MUSHROOM); + public static final ItemStack CACTUS = new ItemStack(Items.CACTUS); + public static final ItemStack MELON = new ItemStack(Items.MELON); + public static final ItemStack PUMPKIN = new ItemStack(Items.PUMPKIN); + public static final ItemStack COCOA_BEANS = new ItemStack(Items.COCOA_BEANS); public static final ItemStack MILESTONE = new ItemStack(Items.LODESTONE); public static final ItemStack PICKAXE = new ItemStack(Items.IRON_PICKAXE); public static final ItemStack NETHER_STAR = new ItemStack(Items.NETHER_STAR); public static final ItemStack HEART_OF_THE_SEA = new ItemStack(Items.HEART_OF_THE_SEA); public static final ItemStack EXPERIENCE_BOTTLE = new ItemStack(Items.EXPERIENCE_BOTTLE); public static final ItemStack PINK_DYE = new ItemStack(Items.PINK_DYE); + public static final ItemStack LIME_DYE = new ItemStack(Items.LIME_DYE); public static final ItemStack ENCHANTED_BOOK = new ItemStack(Items.ENCHANTED_BOOK); public static final ItemStack SPIDER_EYE = new ItemStack(Items.SPIDER_EYE); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java index 9cff3d32..9aa4a50e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/CameraPositionWidget.java @@ -8,8 +8,7 @@ import net.minecraft.util.Formatting; import net.minecraft.util.math.MathHelper; public class CameraPositionWidget extends Widget { - private static final MutableText TITLE = Text.literal("Camera Pos").formatted(Formatting.DARK_PURPLE, - Formatting.BOLD); + private static final MutableText TITLE = Text.literal("Camera Pos").formatted(Formatting.DARK_PURPLE, Formatting.BOLD); private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); public CameraPositionWidget() { @@ -21,17 +20,7 @@ public class CameraPositionWidget extends Widget { double yaw = CLIENT.getCameraEntity().getYaw(); double pitch = CLIENT.getCameraEntity().getPitch(); - this.addComponent( - new PlainTextComponent(Text.literal("Yaw: " + roundToDecimalPlaces(MathHelper.wrapDegrees(yaw), 3)))); - this.addComponent(new PlainTextComponent( - Text.literal("Pitch: " + roundToDecimalPlaces(MathHelper.wrapDegrees(pitch), 3)))); - - } - - // https://stackoverflow.com/a/33889423 - private static double roundToDecimalPlaces(double value, int decimalPlaces) { - double shift = Math.pow(10, decimalPlaces); - - return Math.round(value * shift) / shift; + addComponent(new PlainTextComponent(Text.literal("Yaw: " + String.format("%.3f", MathHelper.wrapDegrees(yaw))))); + addComponent(new PlainTextComponent(Text.literal("Pitch: " + String.format("%.3f", MathHelper.wrapDegrees(pitch))))); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/EmptyWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/EmptyWidget.java new file mode 100644 index 00000000..4c9bcf7f --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/EmptyWidget.java @@ -0,0 +1,12 @@ +package de.hysky.skyblocker.skyblock.tabhud.widget; + +import net.minecraft.text.Text; + +public class EmptyWidget extends Widget { + public EmptyWidget() { + super(Text.empty(), 0); + } + + @Override + public void updateContent() {} +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/Widget.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/Widget.java index e37da755..01a8720b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/Widget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/Widget.java @@ -26,7 +26,7 @@ import net.minecraft.util.Formatting; public abstract class Widget { private final ArrayList<Component> components = new ArrayList<>(); - private int w = 0, h = 0; + protected int w = 0, h = 0; private int x = 0, y = 0; private final int color; private final Text title; @@ -93,6 +93,10 @@ public abstract class Widget { w = Math.max(w, BORDER_SZE_W + BORDER_SZE_E + Widget.txtRend.getWidth(title) + 4 + 4 + 1); } + public final int getX() { + return this.x; + } + public final void setX(int x) { this.x = x; } @@ -101,10 +105,6 @@ public abstract class Widget { return this.y; } - public final int getX() { - return this.x; - } - public final void setY(int y) { this.y = y; } @@ -113,10 +113,27 @@ public abstract class Widget { return this.w; } + public void setWidth(int width) { + this.w = width; + } + public final int getHeight() { return this.h; } + public void setHeight(int height) { + this.h = height; + } + + public void setDimensions(int size) { + setDimensions(size, size); + } + + public void setDimensions(int width, int height) { + this.w = width; + this.h = height; + } + /** * Draw this widget with a background */ diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/FairySouls.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/FairySouls.java index f0e94770..7f826b23 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/FairySouls.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/FairySouls.java @@ -52,7 +52,7 @@ public class FairySouls { @SuppressWarnings("UnusedReturnValue") public static CompletableFuture<Void> runAsyncAfterFairySoulsLoad(Runnable runnable) { if (fairySoulsLoaded == null) { - LOGGER.error("Fairy Souls have not being initialized yet! Please ensure the Fairy Souls module is initialized before modules calling this method in SkyblockerMod#onInitializeClient. This error can be safely ignore in a test environment."); + LOGGER.error("[Skyblocker] Fairy Souls have not being initialized yet! Please ensure the Fairy Souls module is initialized before modules calling this method in SkyblockerMod#onInitializeClient. This error can be safely ignore in a test environment."); return CompletableFuture.completedFuture(null); } return fairySoulsLoaded.thenRunAsync(runnable); @@ -79,10 +79,9 @@ public class FairySouls { try (BufferedReader reader = Files.newBufferedReader(SkyblockerMod.CONFIG_DIR.resolve("found_fairy_souls.json"))) { for (Map.Entry<String, JsonElement> foundFairiesForProfileJson : JsonParser.parseReader(reader).getAsJsonObject().asMap().entrySet()) { for (Map.Entry<String, JsonElement> foundFairiesForLocationJson : foundFairiesForProfileJson.getValue().getAsJsonObject().asMap().entrySet()) { - String profile = foundFairiesForLocationJson.getKey(); - Map<BlockPos, ProfileAwareWaypoint> fairiesForLocation = fairySouls.get(profile); + Map<BlockPos, ProfileAwareWaypoint> fairiesForLocation = fairySouls.get(foundFairiesForLocationJson.getKey()); for (JsonElement foundFairy : foundFairiesForLocationJson.getValue().getAsJsonArray().asList()) { - fairiesForLocation.get(PosUtils.parsePosString(foundFairy.getAsString())).setFound(profile); + fairiesForLocation.get(PosUtils.parsePosString(foundFairy.getAsString())).setFound(foundFairiesForProfileJson.getKey()); } } } diff --git a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java index 880ebe76..70a8c241 100644 --- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java +++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java @@ -25,6 +25,7 @@ import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.function.Predicate; +import java.util.regex.Matcher; import java.util.regex.Pattern; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; @@ -186,6 +187,19 @@ public class ItemUtils { return null; } + @Nullable + public static Matcher getNbtTooltip(ItemStack item, Pattern pattern) { + for (Text line : getNbtTooltips(item)) { + String string = line.getString(); + Matcher matcher = pattern.matcher(string); + if (matcher.matches()) { + return matcher; + } + } + + return null; + } + public static List<Text> getNbtTooltips(ItemStack item) { NbtCompound displayNbt = item.getSubNbt("display"); if (displayNbt == null || !displayNbt.contains("Lore", NbtElement.LIST_TYPE)) { diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java index 08d0b167..3e3bc4af 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Utils.java +++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java @@ -37,6 +37,8 @@ public class Utils { private static final String ALTERNATE_HYPIXEL_ADDRESS = System.getProperty("skyblocker.alternateHypixelAddress", ""); private static final String PROFILE_PREFIX = "Profile: "; + private static final String PROFILE_MESSAGE_PREFIX = "§aYou are playing on profile: §e"; + public static final String PROFILE_ID_PREFIX = "Profile ID: "; private static boolean isOnHypixel = false; private static boolean isOnSkyblock = false; private static boolean isInjected = false; @@ -424,10 +426,14 @@ public class Utils { return shouldFilter; } - if (isOnSkyblock && message.startsWith("Profile ID: ")) { - profileId = message.replace("Profile ID: ", ""); + if (isOnSkyblock) { + if (message.startsWith(PROFILE_MESSAGE_PREFIX)) { + profile = message.substring(PROFILE_MESSAGE_PREFIX.length()).split("§b")[0]; + } else if (message.startsWith(PROFILE_ID_PREFIX)) { + profileId = message.substring(PROFILE_ID_PREFIX.length()); - MuseumItemCache.tick(profileId); + MuseumItemCache.tick(profileId); + } } return true; diff --git a/src/main/resources/assets/skyblocker/dungeons/secretlocations.json b/src/main/resources/assets/skyblocker/dungeons/secretlocations.json index 0f22f597..760e72d9 100644 --- a/src/main/resources/assets/skyblocker/dungeons/secretlocations.json +++ b/src/main/resources/assets/skyblocker/dungeons/secretlocations.json @@ -4730,7 +4730,7 @@ "z":15 }, { - "secretName":"2 - Stonk", + "secretName":"1 - Stonk", "category":"stonk", "x":26, "y":112, diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index d568af65..ff0ffa11 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -32,7 +32,6 @@ "text.autoconfig.skyblocker.option.general.experiments.enableSuperpairsSolver": "Enable Superpairs Solver", "text.autoconfig.skyblocker.option.general.experiments.enableUltrasequencerSolver": "Enable Ultrasequencer Solver", "text.autoconfig.skyblocker.option.general.acceptReparty": "Auto accept Reparty", - "text.autoconfig.skyblocker.option.general.visitorHelper": "Visitor helper", "text.autoconfig.skyblocker.option.general.etherwarpOverlay": "Etherwarp Overlay", "text.autoconfig.skyblocker.option.general.fishing": "Fishing Helper", "text.autoconfig.skyblocker.option.general.fishing.enableFishingHelper": "Enable Fishing Helper", @@ -68,6 +67,8 @@ "text.autoconfig.skyblocker.option.general.tabHud.tabHudEnabled": "Enable fancy tab HUD", "text.autoconfig.skyblocker.option.general.tabHud.tabHudScale": "Scale factor of fancy tab HUD", "text.autoconfig.skyblocker.option.general.tabHud.tabHudScale.@Tooltip": "Value in %, relative to your vanilla GUI scale", + "text.autoconfig.skyblocker.option.general.tabHud.enableHudBackground": "Enable HUD Background", + "text.autoconfig.skyblocker.option.general.tabHud.enableHudBackground.@Tooltip": "Enables the background of the non-tab HUD.", "text.autoconfig.skyblocker.option.general.tabHud.plainPlayerNames": "Plain Player Names", "text.autoconfig.skyblocker.option.general.tabHud.plainPlayerNames.@Tooltip":"Enable to display player names without any special formatting on public islands.", "text.autoconfig.skyblocker.option.general.tabHud.nameSorting": "Player Name Sorting Method", @@ -201,7 +202,10 @@ "text.autoconfig.skyblocker.option.locations.spidersDen.relics.enableRelicsHelper": "Enable Hidden Relics Helper", "text.autoconfig.skyblocker.option.locations.spidersDen.relics.highlightFoundRelics": "Highlight Found Relics", "text.autoconfig.skyblocker.option.locations.garden": "Garden", + "text.autoconfig.skyblocker.option.locations.garden.farmingHud.enableHud": "Enable Farming HUD", + "text.autoconfig.skyblocker.option.locations.garden.farmingHud.config": "Farming HUD Config...", "text.autoconfig.skyblocker.option.locations.garden.dicerTitlePrevent": "Enable Dicer Title Prevent", + "text.autoconfig.skyblocker.option.locations.garden.visitorHelper": "Visitor helper", "text.autoconfig.skyblocker.option.locations.dungeons": "Dungeons", "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints": "Dungeon Secret Waypoints", "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableRoomMatching": "Enable Room Matching", @@ -315,7 +319,6 @@ "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[1]": "\nFancy: Shows name, percentage, progress bar and an icon.", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[2]": "\nClassic: Shows name and percentage in a very simple box.", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.screen": "Dwarven HUD Config...", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "Enable Background", "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud": "Crystal Hollows Map", "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.enabled": "Enabled", "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.screen": "Crystal Hollows Map Placement Config...", @@ -424,9 +427,10 @@ "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.sounds.amethyst": "Amethyst", "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.sounds.anvil": "Break", "text.autoconfig.skyblocker.category.slayer": "Slayers", - "text.autoconfig.skyblocker.option.slayer.endermanSlayer": "[Beta] Enderman Slayer", - "text.autoconfig.skyblocker.option.slayer.endermanSlayer.highlightNukekubiHeads": "Nukekubi Head Highlighting", + "text.autoconfig.skyblocker.option.slayer.endermanSlayer": "Enderman Slayer", + "text.autoconfig.skyblocker.option.slayer.endermanSlayer.enableYangGlyphsNotification": "Enable Yang Glyphs notification", "text.autoconfig.skyblocker.option.slayer.endermanSlayer.highlightBeacons": "Beacon Highlighting", + "text.autoconfig.skyblocker.option.slayer.endermanSlayer.highlightNukekubiHeads": "Nukekubi Head Highlighting", "text.autoconfig.skyblocker.option.slayer.vampireSlayer": "Vampire Slayer", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.enableEffigyWaypoints": "Enable Effigy Waypoints", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.compactEffigyWaypoints": "Compact Effigy Waypoints", diff --git a/src/main/resources/assets/skyblocker/lang/es_es.json b/src/main/resources/assets/skyblocker/lang/es_es.json index d74ac193..3f147a25 100644 --- a/src/main/resources/assets/skyblocker/lang/es_es.json +++ b/src/main/resources/assets/skyblocker/lang/es_es.json @@ -42,7 +42,6 @@ "text.autoconfig.skyblocker.option.messages.hideImplosion": "Ocultar el mensaje de Implosion", "text.autoconfig.skyblocker.option.messages.hideCombo": "Ocultar Mensajes de Combos", "text.autoconfig.skyblocker.option.locations.dungeons.croesusHelper.@Tooltip": "Obscurece los cofres que ya han sido abiertos.", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "Habilitar Fondo", "text.autoconfig.skyblocker.option.general.itemTooltip": "Información extra de los objetos", "skyblocker.itemTooltip.nullMessage": "§cEl precio en la información en los objetos se actualiza cada 60 segundos. De lo contrario revisa lastest.log", "text.autoconfig.skyblocker.option.richPresence.info.@Tooltip": "Este valor no importa si estas ciclando", diff --git a/src/main/resources/assets/skyblocker/lang/fr_fr.json b/src/main/resources/assets/skyblocker/lang/fr_fr.json index 679f2507..c3c8bbeb 100644 --- a/src/main/resources/assets/skyblocker/lang/fr_fr.json +++ b/src/main/resources/assets/skyblocker/lang/fr_fr.json @@ -49,7 +49,6 @@ "text.autoconfig.skyblocker.option.locations.dwarvenMines.solveFetchur": "Décoder les requêtes de Fetchur", "text.autoconfig.skyblocker.option.locations.dwarvenMines.solvePuzzler": "Résoudre le puzzle de Puzzler", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud": "ATH mine des nains", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "Activer l'arrière-plan", "text.autoconfig.skyblocker.category.messages": "Messages", "text.autoconfig.skyblocker.option.messages.hideAbility": "Cacher le rechargement des capacités", "text.autoconfig.skyblocker.option.messages.hideHeal": "Cacher les messages de soin", @@ -148,5 +147,37 @@ "text.autoconfig.skyblocker.option.general.waypoints.waypointType.@Tooltip": "Waypoint : Affiche une accentuation et faisceau de beacon.\n\nWaypoint avec contour : Affiche un waypoint ET un contour.\n\nAccentuation : Affiche seulement une accentuation.\n\nAccentuation avec contour : Affiche une accentuation ET un contour.\n\nContour : Affiche seulement un contour.", "text.autoconfig.skyblocker.option.general.waypoints.waypointType.generalNote": "\n\n\nCette option ne s'applique pas a tout les waypoints. Certains waypoints comme les waypoints pour secrets ont leur propre configuration.", "text.autoconfig.skyblocker.option.general.tabHud.plainPlayerNames": "Noms de Joueurs Clairs", - "text.autoconfig.skyblocker.option.general.itemInfoDisplay": "Affichage des infos d'item" + "text.autoconfig.skyblocker.option.general.itemInfoDisplay": "Affichage des infos d'item", + "text.autoconfig.skyblocker.option.general.itemTooltip.enableMotesPrice": "Activer le prix des motes", + "text.autoconfig.skyblocker.option.general.chestValue.@Tooltip": "Calcule la valeur du contenant.", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgroundStyle.@Tooltip": "Choisit entre un style rond ou carré!", + "text.autoconfig.skyblocker.option.general.teleportOverlay.enableTeleportOverlays": "Activer l'overlay de téléportation", + "text.autoconfig.skyblocker.option.general.teleportOverlay": "Overlay de téléportation", + "text.autoconfig.skyblocker.option.general.itemCooldown": "Temps d'attente pour utiliser l'objet", + "text.autoconfig.skyblocker.option.general.chestValue": "Valeur du coffre", + "text.autoconfig.skyblocker.option.general.chestValue.enableChestValue": "Active la valeur des coffres", + "text.autoconfig.skyblocker.option.general.chestValue.color": "Couleur des valeurs des coffres", + "text.autoconfig.skyblocker.option.general.chestValue.incompleteColor": "Couleur de valeur incomplète", + "text.autoconfig.skyblocker.option.general.chestValue.incompleteColor.@Tooltip": "La couleur a afficher quand le informations sur les prix sont incomplètes.", + "key.itemProtection": "Protéger l'objet", + "text.autoconfig.skyblocker.option.general.itemTooltip.enableMotesPrice.@Tooltip": "Afficher le prix de vente d'un objet en Motes dans le Rift", + "text.autoconfig.skyblocker.option.general.chestValue.enableChestValue.@Tooltip": "Ajoute un bouton dans les contenants permettant de calculer leur valeur.", + "text.autoconfig.skyblocker.option.general.specialEffects": "Effets spéciaux", + "text.autoconfig.skyblocker.option.general.titleContainer.@Tooltip": "Utilisé pour afficher plusieurs titres à la fois, Exemple: Vampire Slayer", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgrounds.@Tooltip": "Affiche un fond coloré derrière les objets, la couleur représente la rareté de l'objet.", + "text.autoconfig.skyblocker.option.general.wikiLookup.enableWikiLookup.@Tooltip": "Ouvre la page du wiki de l'objet survolé avec la touche F4.", + "text.autoconfig.skyblocker.option.general.wikiLookup.officialWiki.@Tooltip": "Utilise le wiki officiel plutôt que le wiki Fandom.", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.attributeShardInfo.@Tooltip": "Afficher le niveau de l'attribut avec le nombre d'items et les initiales du nom de l'attribut.", + "text.autoconfig.skyblocker.option.general.wikiLookup.officialWiki": "Utiliser le wiki officiel", + "text.autoconfig.skyblocker.option.general.itemProtection.slotLockStyle": "Style de l'icône de verrouillage d'emplacement", + "text.autoconfig.skyblocker.option.general.dungeonQuality": "Qualité du donjon", + "text.autoconfig.skyblocker.option.general.dungeonQuality.@Tooltip": "Affiche la qualité et le niveau des objets lâchés par les ennemis des donjons à leur mort.\n\n\nRappel:\nNiveau 1-3 lâchés en F1-F3\nNiveau 4-7 lâchés en F4-F7 ou M1-M4\nNiveau 8-10 lâchés en M5-M7", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.attributeShardInfo": "Info des fragments d'attributs", + "text.autoconfig.skyblocker.option.general.specialEffects.rareDungeonDropEffects": "Effet de drop de donjon rare", + "text.autoconfig.skyblocker.option.general.specialEffects.rareDungeonDropEffects.@Tooltip": "Ajoute un effet visuel spécial activé en obtenant un objet de donjon rare!", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableBazaar": "Activer pour le Bazaar", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableAuctionHouse": "Activer pour la maison des enchères", + "text.autoconfig.skyblocker.option.general.searchOverlay.keepPreviousSearches": "Sauvegarder les précédentes recherches", + "text.autoconfig.skyblocker.option.general.searchOverlay.maxSuggestions": "Suggestions maximums", + "text.autoconfig.skyblocker.option.general.searchOverlay.maxSuggestions.@Tooltip": "Le nombre maximum d'objets suggérés à montrer." } diff --git a/src/main/resources/assets/skyblocker/lang/ja_jp.json b/src/main/resources/assets/skyblocker/lang/ja_jp.json index 19e8a52c..da096e8b 100644 --- a/src/main/resources/assets/skyblocker/lang/ja_jp.json +++ b/src/main/resources/assets/skyblocker/lang/ja_jp.json @@ -46,7 +46,6 @@ "text.autoconfig.skyblocker.option.locations.dwarvenMines.solveFetchur": "Fetchurの要求アイテムの表示", "text.autoconfig.skyblocker.option.locations.dwarvenMines.solvePuzzler": "Puzzler Puzzleのソルバー", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud": "ドワーフマインでのHUD", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "バックグラウンド表示を有効にする", "text.autoconfig.skyblocker.category.messages": "メッセージ", "text.autoconfig.skyblocker.option.messages.hideAbility": "アビリティのクールダウンを非表示にする", "text.autoconfig.skyblocker.option.messages.hideHeal": "回復メッセージを非表示にする", diff --git a/src/main/resources/assets/skyblocker/lang/ko_kr.json b/src/main/resources/assets/skyblocker/lang/ko_kr.json index 4fa1e135..d7532b68 100644 --- a/src/main/resources/assets/skyblocker/lang/ko_kr.json +++ b/src/main/resources/assets/skyblocker/lang/ko_kr.json @@ -62,7 +62,6 @@ "text.autoconfig.skyblocker.option.locations.dwarvenMines.solveFetchur": "Fetchur 해결", "text.autoconfig.skyblocker.option.locations.dwarvenMines.solvePuzzler": "Puzzler 퍼즐 해결", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud": "Dwarven HUD", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "배경 활성화", "text.autoconfig.skyblocker.category.messages": "메시지", "text.autoconfig.skyblocker.option.messages.chatFilterResult.PASS": "비활성화됨", "text.autoconfig.skyblocker.option.messages.chatFilterResult.FILTER": "필터", diff --git a/src/main/resources/assets/skyblocker/lang/pt_br.json b/src/main/resources/assets/skyblocker/lang/pt_br.json index ac7e0a6c..4982c154 100644 --- a/src/main/resources/assets/skyblocker/lang/pt_br.json +++ b/src/main/resources/assets/skyblocker/lang/pt_br.json @@ -203,7 +203,6 @@ "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud": "Interface da mina dos anões", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style": "Estilo para a interface", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[2]": "\nClássico: Exibe nome e porcentagem em uma caixa super simples.", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "Ativar fundo", "text.autoconfig.skyblocker.option.locations.rift.mcGrubberStacks": "Pilhas de McGrubber", "text.autoconfig.skyblocker.option.messages.chatFilterResult.PASS": "Desativado", "text.autoconfig.skyblocker.option.messages.chatFilterResult.FILTER": "Filtro", diff --git a/src/main/resources/assets/skyblocker/lang/ru_ru.json b/src/main/resources/assets/skyblocker/lang/ru_ru.json index 00bf4025..a98ac9b4 100644 --- a/src/main/resources/assets/skyblocker/lang/ru_ru.json +++ b/src/main/resources/assets/skyblocker/lang/ru_ru.json @@ -18,7 +18,7 @@ "text.autoconfig.skyblocker.category.messages": "Сообщения", "text.autoconfig.skyblocker.option.messages.hideAbility": "Скрывать сообщения о перезарядке способностей", "text.autoconfig.skyblocker.option.messages.hideHeal": "Скрывать сообщения об исцелении", - "text.autoconfig.skyblocker.option.messages.hideAOTE": "Скрывать сообщения AOTE/AOTV", + "text.autoconfig.skyblocker.option.messages.hideAOTE": "Скрывать сообщения способности перемещения", "text.autoconfig.skyblocker.option.messages.hideImplosion": "Скрывать сообщения Implosion", "text.autoconfig.skyblocker.option.messages.hideMoltenWave": "Скрывать сообщения Molten Wave", "text.autoconfig.skyblocker.option.messages.hideAds": "Скрывать рекламу в чате", @@ -88,7 +88,6 @@ "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style": "Стиль HUD", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[0]": "Упрощенный: Показывает название и процент выполнения.", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[2]": "\nКлассический: Показывает название и процент выполнения в простом тёмном квадрате.", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "Включить Фон", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud": "Dwarven HUD (Интерфейс Гномьих Шахт)", "text.autoconfig.skyblocker.option.messages.hideMana.@Tooltip": "Выглядит лучше, когда включены полоски Skyblocker (здоровья, маны и т.д.)", "text.autoconfig.skyblocker.option.locations.barn": "Barn (Ферма)", @@ -102,10 +101,10 @@ "text.autoconfig.skyblocker.option.locations.dungeons.croesusHelper": "Помощь в меню Croesus", "text.autoconfig.skyblocker.option.general.experiments": "Помощь в Экспериментах", "text.autoconfig.skyblocker.option.general.experiments.enableUltrasequencerSolver": "Решать Ultrasequencer", - "skyblocker.fairySouls.markAllFound": "Все души фей (fairy souls), которые есть на этом острове, теперь отмечены как найденные", + "skyblocker.fairySouls.markAllFound": "§b[§6Skyblocker§b] §rПометил все fairy souls на текущем острове как найденные", "text.autoconfig.skyblocker.option.general.experiments.enableChronomatronSolver": "Решать Chronomatron", "text.autoconfig.skyblocker.option.general.experiments.enableSuperpairsSolver": "Подсвечивать Пары Superpairs", - "skyblocker.fairySouls.markAllMissing": "Все души фей (fairy souls), которые есть на этом острове, теперь отмечены как еще не найденные", + "skyblocker.fairySouls.markAllMissing": "§b[§6Skyblocker§b] §rПометил все души фей на текущем острове как пропущенные", "text.autoconfig.skyblocker.option.general.fairySouls": "Помощь В Нахождении Fairy Souls (Душ Фей)", "text.autoconfig.skyblocker.option.general.fairySouls.enableFairySoulsHelper": "Включить Помощь В Поиске Fairy Souls", "text.autoconfig.skyblocker.option.general.itemTooltip.enableMotesPrice": "Показать Цену Motes", @@ -113,7 +112,7 @@ "text.autoconfig.skyblocker.option.locations.rift.mcGrubberStacks.@Tooltip": "Используется для рассчета цены предмета в Motes.", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.compactEffigyWaypoints": "Показывать Вейпоинты Effigy Компактно", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.effigyUpdateFrequency.@Tooltip": "Чем ниже значение, тем чаще происходит обновление, это может вызвать лаги.", - "text.autoconfig.skyblocker.option.locations.rift": "The Rift", + "text.autoconfig.skyblocker.option.locations.rift": "Разлом", "text.autoconfig.skyblocker.option.locations.rift.mirrorverseWaypoints": "Включить Вейпоинты в Mirrorverse", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.enableHealingMelonIndicator": "Включить Индикатор Healing Melon", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.healingMelonHealthThreshold": "Предел Индикатора Healing Melon (в сердечках)", @@ -125,8 +124,8 @@ "skyblocker.rift.healNow": "Арбуз!", "text.autoconfig.skyblocker.option.general.acceptReparty": "Автоматически принимать Reparty (Приглашение в новую группу от лидера предыдущей)", "text.autoconfig.skyblocker.option.locations.rift.mcGrubberStacks": "Стаков McGrubber", - "text.autoconfig.skyblocker.category.slayer": "Slayers", - "text.autoconfig.skyblocker.option.slayer.vampireSlayer": "Vampire Slayer", + "text.autoconfig.skyblocker.category.slayer": "Слеерство", + "text.autoconfig.skyblocker.option.slayer.vampireSlayer": "Вампир-слеер", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.effigyUpdateFrequency": "Частота Обновления Вейпоинтов Effigy (в тиках)", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.enableEffigyWaypoints": "Включить Вейпоинты Effigy", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.enableHolyIceIndicator": "Включить Индикатор Holy Ice", @@ -137,16 +136,220 @@ "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandShortcuts": "Включить Сокращения Команд", "text.autoconfig.skyblocker.option.general.shortcuts": "Сокращения", "text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts": "Включить Сокращения", - "text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts.@Tooltip": "Работает только на Хайпикселе. Сокращения можно редактировать при помощи \"/skyblocker shortcuts\". Хотя бы одна из опций должна быть включена, чтобы это работало.", + "text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts.@Tooltip": "Работает где угодно, даже на ваниле! Сокращения можно редактировать при помощи \"/skyblocker shortcuts\". Хотя бы одна из опций должна быть включена, чтобы это работало.", "text.autoconfig.skyblocker.option.general.tabHud.nameSorting": "Метод сортировки имен игроков", - "key.skyblocker.toggleB": "Переключить интерфейс Tab на экран B", - "key.skyblocker.toggleA": "Переключить интерфейс Tab на экран A", - "text.autoconfig.skyblocker.option.general.tabHud.plainPlayerNames": "Чистые Имена Игроков", - "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandShortcuts.@Tooltip": "Сокращения для команд, состоящие из только одного слова вместо нескольких. Сокращения можно отредактировать при помощи \"/skyblocker shortcuts\". Необходимо включить сокращения, чтобы это работало.", + "key.skyblocker.toggleB": "Включение вкладки HUD на экране B", + "key.skyblocker.toggleA": "Включение вкладки HUD на экране A", + "text.autoconfig.skyblocker.option.general.tabHud.plainPlayerNames": "Простые имена игроков", + "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandShortcuts.@Tooltip": "Сокращения для команд, состоящих только из одного слова. Редактируйте сокращения с помощью команды \"/skyblocker shortcuts\". Для того, чтобы эта функция начала действовать, сокращения должны быть включены.", "text.autoconfig.skyblocker.option.general.quiverWarning": "Предупреждение о нехватке стрел", "text.autoconfig.skyblocker.option.general.quiverWarning.enableQuiverWarning": "Включить предупреждение о нехватке стрел", "text.autoconfig.skyblocker.option.general.quiverWarning.enableQuiverWarningInDungeons": "Включить предупреждение о нехватке стрел (только в данжах)", "text.autoconfig.skyblocker.option.general.quiverWarning.enableQuiverWarningAfterDungeon": "Включить предупреждение о нехватке стрел (после прохождения данжа)", "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandArgShortcuts": "Включить сокращения аргументов команд", - "text.autoconfig.skyblocker.option.slayer.vampireSlayer.maniaUpdateFrequency.@Tooltip": "Чем меньше значение, тем чаще происходит обновление, что может привести к лагам." + "text.autoconfig.skyblocker.option.slayer.vampireSlayer.maniaUpdateFrequency.@Tooltip": "Чем меньше значение, тем чаще происходит обновление, что может привести к лагам.", + "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandArgShortcuts.@Tooltip": "Сокращения, которые заменяют одно или больше слов/аргументов команды, которая имеет множество слов/аргументов. Редактируйте сокращения с помощью \"/skyblocker shortcuts\". Сокращения должны быть включены, чтобы это вступило в силу.", + "text.autoconfig.skyblocker.option.general.waypoints.waypointType.@Tooltip": "Стандартная метка: показывается столб света от маяка.\n\nКонтур метки: отображает метки и её обводку, также показывает столб света маяка.\n\nПодсветка: Просто подсвечивает метку.\n\nПодсветка с контуром: подсвечивает метку и показывает её контур.\n\nКонтур: Просто показывает контур метки.", + "text.autoconfig.skyblocker.option.general.waypoints.waypointType.generalNote": "\n\n\nЭти настройки применяются не ко всем меткам. Некоторые из меток, например секретные, имеют персональную настройку.", + "text.autoconfig.skyblocker.option.general.tabHud.plainPlayerNames.@Tooltip": "Включить показ никнеймов игроков на публичном острове без специального форматирования.", + "text.autoconfig.skyblocker.option.general.mythologicalRitual": "Помощник с мифологическими ритуалами", + "text.autoconfig.skyblocker.option.general.mythologicalRitual.enableMythologicalRitualHelper": "Включить помощь с мифологическими ритуалами", + "text.autoconfig.skyblocker.option.general.itemTooltip.enableObtainedDate": "Включить дату получения", + "text.autoconfig.skyblocker.option.general.waypoints.enableWaypoints": "Включить метки на карте", + "text.autoconfig.skyblocker.option.general.waypoints": "Метки на карте", + "text.autoconfig.skyblocker.option.general.waypoints.waypointType": "Тип меток", + "text.autoconfig.skyblocker.option.general.itemCooldown.enableItemCooldowns": "Включить задержку предмета", + "text.autoconfig.skyblocker.option.general.itemCooldown": "Задержка предмета", + "text.autoconfig.skyblocker.option.general.compactorDeletorPreview": "Включить предпросмотр Compactor/Deletor", + "text.autoconfig.skyblocker.option.general.itemTooltip.enableMuseumInfo": "Включить музейную информацию", + "text.autoconfig.skyblocker.option.general.tabHud.nameSorting.@Tooltip": "Алфавитная сортировка сортирует имена в алфавитном порядке, в то время как сортировка по умолчанию не имеет определенного порядка.", + "text.autoconfig.skyblocker.option.quickNav.button.item.count": "Кол-во предметов", + "text.autoconfig.skyblocker.option.quickNav.button.item.nbt": "NBT-информация", + "text.autoconfig.skyblocker.option.general.fairySouls.highlightOnlyNearbySouls": "Подсвечивать только ближайшие Fairy Souls", + "text.autoconfig.skyblocker.option.general.fairySouls.highlightOnlyNearbySouls.@Tooltip": "Когда включено, Fairy Souls в радиусе 50 блоков подсвечиваются", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.suppliesAndFuelWaypointType": "Тип Пополняющих/Заправочных меток", + "text.autoconfig.skyblocker.option.general.fairySouls.highlightFoundSouls": "Подсвечивать найденные Fairy Souls", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableChestWaypoints": "Включить метки сундуков", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableSuperboomWaypoints": "Включить метки для Супербомб", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableStonkWaypoints": "Включить метки Stonk'ов", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enablePearlWaypoints": "Включить метки пёрлов", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enablePearlWaypoints.@Tooltip": "Показывает место, куда вас перенесёт при броске пёрла или использования Аспекта Энда.", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableAotvWaypoints": "Включить метку Аспекта Энда", + "text.autoconfig.skyblocker.option.general.teleportOverlay.enableEtherTransmission": "Включить оверлей эфейрого перемещения", + "text.autoconfig.skyblocker.option.general.flameOverlay": "Показ огня", + "text.autoconfig.skyblocker.option.general.flameOverlay.flameHeight": "Высота огня", + "text.autoconfig.skyblocker.option.general.flameOverlay.flameOpacity": "Видимость огня", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableDefaultWaypoints.@Tooltip": "Сюда входят все метки без категорий.", + "text.autoconfig.skyblocker.option.general.titleContainer": "Область текста", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.doorHighlightType.@Tooltip": "Подсветка: Просто подсветка двери.\n\nКонтур и подсветка: Подсвечивает дверь и показывает обводку.\n\nКонтур: Показывает только контур двери.", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.doorHighlightType": "Тип подсветки двери", + "text.autoconfig.skyblocker.option.general.chestValue": "Суммарная стоимость хранилища", + "text.autoconfig.skyblocker.option.general.chestValue.@Tooltip": "Считает рыночную стоимость всех предметов в хранилище.", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints": "Метки данжевых секретов", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableSecretWaypoints": "Включить метки секреток данжа", + "text.autoconfig.skyblocker.option.general.titleContainer.titleContainerScale": "Размер отображаемого текста", + "text.autoconfig.skyblocker.option.general.teleportOverlay.enableInstantTransmission": "Включить оверлей моментального перемещения", + "text.autoconfig.skyblocker.option.locations.garden": "Сад", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableItemWaypoints": "Включить метки предметов", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableBatWaypoints": "Включить метки летучих мышей", + "text.autoconfig.skyblocker.option.locations.garden.dicerTitlePrevent": "Включить показ предупреждения дайсера", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.doorHighlightType.secretWaypointsNote": "\n\n\nПримечание: Чтобы это работало, надо включить секретные метки данжа.", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreMessage": "Включить оповещение при %d очках", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreSound": "Включить звуковое оповещение о достижении %d очков", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreSound.@Tooltip": "Проигрывает звук при получении %d очков.", + "text.autoconfig.skyblocker.option.locations.spidersDen": "Паучье логово", + "text.autoconfig.skyblocker.option.locations.spidersDen.relics": "Помощник по спрятанным реликвиям", + "text.autoconfig.skyblocker.option.general.specialEffects": "Спецэффекты", + "text.autoconfig.skyblocker.option.general.specialEffects.rareDungeonDropEffects": "Показ редкости данж-дропа эффектом", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableRoomMatching.@Tooltip": "Отключение сэкономит 20 МБ ОЗУ, но метки секретов и некоторые пазлы требуют включение этой функции.", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableRoomMatching": "Включить нумерацию комнат", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableDefaultWaypoints": "Включить стандартные метки", + "skyblocker.wikiLookup.noArticleFound": "§rДля этого предмета не найдено статьи на Вики...", + "text.autoconfig.skyblocker.option.general.betterPartyFinder": "Улучшенный поиск компании", + "text.autoconfig.skyblocker.option.locations.spidersDen.relics.highlightFoundRelics": "Подсветка найденных реликвий", + "text.autoconfig.skyblocker.option.locations.spidersDen.relics.enableRelicsHelper": "Включить помощника по хайд-реликвиям", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.showSecretText": "Включить секретный текст", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreTitle": "Включить титры при получении %d очков", + "text.autoconfig.skyblocker.option.general.teleportOverlay.enableWitherImpact": "Включить показ эффекта иссушения", + "text.autoconfig.skyblocker.option.general.wikiLookup.enableWikiLookup": "Включить поиск на Вики", + "text.autoconfig.skyblocker.option.general.wikiLookup.enableWikiLookup.@Tooltip": "При наведении на предмет и нажатии F4 вас перенесёт на вики-страницу этого предмета.", + "text.autoconfig.skyblocker.option.general.wikiLookup.officialWiki": "Использовать официальную Вики", + "text.autoconfig.skyblocker.option.general.wikiLookup": "Вики-поиск", + "text.autoconfig.skyblocker.option.general.wikiLookup.officialWiki.@Tooltip": "Используйте официальную Вики вместо фандом-версии.", + "text.autoconfig.skyblocker.option.general.specialEffects.rareDungeonDropEffects.@Tooltip": "Добавляет спецэффект при получении редкого лута данжа!", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.dungeonScoreMessage": "Сообщение о достижении %d очков", + "text.autoconfig.skyblocker.option.general.flameOverlay.flameHeight.@Tooltip": "100% стандартная высота\n0% выключить", + "text.autoconfig.skyblocker.option.general.flameOverlay.flameOpacity.@Tooltip": "100% стандартная видимость\n0% прозрачный", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreMessage.@Tooltip": "Отправляет в чат сообщение о достижении %d очков в данже.", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreTitle.@Tooltip": "Показывает титры о достижении %d очков в данже.", + "text.autoconfig.skyblocker.option.general.enableTips": "Включить подсказки", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableFairySoulWaypoints": "Включить метки душ фей", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight": "Подсветка дверей", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.enableDoorHighlight.@Tooltip": "Подсвечивает Визер и Кровавые двери красным, если закрыто, и зелёным, если открыто.", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.enableDoorHighlight": "Включить подсветку двери", + "text.autoconfig.skyblocker.option.general.itemProtection.slotLockStyle.@Tooltip": "Выбор между красивым и классическим вариантом значка.", + "text.autoconfig.skyblocker.option.general.chestValue.enableChestValue": "Включить подсчёт хранилища", + "text.autoconfig.skyblocker.option.general.titleContainer.config": "Настройки расположения текста...", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.supplyWaypoints": "Метки снабжения", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.fuelWaypoints": "Заправочные точки", + "text.autoconfig.skyblocker.category.crimsonIsle": "Багровый остров", + "key.itemProtection": "Защита предмета", + "text.autoconfig.skyblocker.option.quickNav.button": "Кнопка %d", + "text.autoconfig.skyblocker.option.quickNav.button.render": "Прорисовка", + "text.autoconfig.skyblocker.option.quickNav.button.item": "Предмет", + "text.autoconfig.skyblocker.option.general.chestValue.color": "Цвет счётчика хранилища", + "text.autoconfig.skyblocker.option.general.chestValue.enableChestValue.@Tooltip": "Добавляет кнопку для подсчёта стоимости хранилища.", + "text.autoconfig.skyblocker.option.general.chestValue.incompleteColor": "Цвет неполного подсчёта", + "text.autoconfig.skyblocker.option.general.chestValue.incompleteColor.@Tooltip": "Этот цвет показывает стоимость хранилища при неполной информации о стоимостях.", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.ballistaBuildWaypoints": "Метка баллистической постройки", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.safeSpotWaypoints": "Метки сейф-зон", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.pearlWaypoints": "Метки пёрлов", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.noArrowPoisonWarning.@Tooltip": "Предупреждает вас о отсутствии яда для токсичных стрел в инвентаре. Работает только в DPS-фазе.", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableEntranceWaypoints": "Включить метки входов", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableWitherWaypoints": "Включить метки Визер-эссенций", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableLeverWaypoints": "Включить метки рычагов", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore": "Счёт очков данжа", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.noArrowPoisonWarning": "Выключить предупреждение о ядовитых стрелах", + "text.autoconfig.skyblocker.option.general.searchOverlay": "Интерфейс поиска", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableBazaar": "Включить на Базаре", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableBazaar.@Tooltip": "Показывает кастомный интерфейса поиск на базаре вместо стандартного.", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableAuctionHouse": "Включить на Аукционе", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableAuctionHouse.@Tooltip": "Показывает кастомный интерфейс поиска на аукционе вместо стандартного.", + "text.autoconfig.skyblocker.option.general.searchOverlay.keepPreviousSearches": "Сохранять предыдущий поиск", + "text.autoconfig.skyblocker.option.general.searchOverlay.historyLength": "Длина сохраняемого запроса поиска", + "text.autoconfig.skyblocker.option.general.searchOverlay.historyLength.@Tooltip": "Длина истории для интерфейса поиска.", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableCommands": "Открывать из команд", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableCommands.@Tooltip": "Открывает интерфейс поиска базара и аукциона \"/bzs\" и \"/ahs\" соответственно. Для применения настроек надо перезагрузиться.", + "text.autoconfig.skyblocker.option.general.searchOverlay.historyLabel": "История:", + "text.autoconfig.skyblocker.option.quickNav.button.item.itemName": "ID предмета", + "text.autoconfig.skyblocker.option.quickNav.button.clickEvent": "Выполнение при нажатии", + "text.autoconfig.skyblocker.option.general.searchOverlay.keepPreviousSearches.@Tooltip": "Сохраняет несколько предыдущих запросов поиска.", + "text.autoconfig.skyblocker.option.general.searchOverlay.maxSuggestions": "Максимальная длина истории поиска", + "text.autoconfig.skyblocker.option.general.searchOverlay.maxSuggestions.@Tooltip": "Максимальное значение истории предыдущих запросов.", + "text.autoconfig.skyblocker.option.quickNav.button.uiTitle": "Отображаемое название", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.attributeShardInfo.@Tooltip": "Отображение уровня атрибута в виде количества стаков и инициалов имени атрибута.", + "text.autoconfig.skyblocker.option.general.teleportOverlay": "Оверлей телепорта", + "text.autoconfig.skyblocker.option.general.titleContainer.@Tooltip": "Используется для одновременного отображения нескольких названий, пример использования: Vampire Slayer", + "text.autoconfig.skyblocker.option.slayer.vampireSlayer.enableManiaIndicator": "Включить индикатор Mania Block", + "skyblocker.dungeons.secrets.physicalEntranceNotFound": "§b[§6Skyblocker§b] §cКоординаты входной комнаты подземелья не найдены. Пожалуйста, вернитесь в зеленую комнату входа.", + "text.autoconfig.skyblocker.option.general.teleportOverlay.enableTeleportOverlays": "Включить Оверлэй телепорта", + "text.autoconfig.skyblocker.option.slayer.vampireSlayer.maniaUpdateFrequency": "Частота обновления индикатора Mania (тики)", + "text.skyblocker.quit_config": "Изменения не сохранены", + "text.skyblocker.quit_config_sure": "Вы уверены, что хотите прекратить редактировать настройки? Изменения не будут сохранены!", + "text.skyblocker.open": "Открыть", + "text.skyblocker.quit_discard": "Выйти и отменить изменения", + "text.autoconfig.skyblocker.option.general.shortcuts.config": "Настройка сокращений...", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.attributeShardInfo": "Информация об Attribute Shard", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay": "Отображение информации о предмете", + "skyblocker.dungeons.secrets.markSecretMissing": "§b[§6Skyblocker§b] §rПометил секрет #%d как пропущенный.", + "text.autoconfig.skyblocker.option.general.hideStatusEffectOverlay": "Скрыть отображение статуса эффектов", + "skyblocker.dungeons.secrets.markSecretFound": "§b[§6Skyblocker§b] §гПометил секрет #%d как найденный.", + "skyblocker.dungeons.secrets.markSecretMissingUnable": "§b[§6Skyblocker§b] §cНевозможно отметить секрет #%d как пропущенный.", + "skyblocker.dungeons.secrets.markSecretFoundUnable": "§b[§6Skyblocker§b] §cНевозможно отметить секрет #%d как найденный.", + "skyblocker.rift.mania": "Мания!", + "skyblocker.relics.markAllFound": "§b[§6Skyblocker§b] §rПометил все реликвии как найденные", + "skyblocker.relics.markAllMissing": "§b[§6Skyblocker§b] §rПометил все реликвии как пропущенные", + "skyblocker.shortcuts.config": "Настройка сокращений", + "skyblocker.shortcuts.commandSuggestionTooltip": "В связи с ограничениями Minecraft предложения команд будут работать только после перезапуска игры.", + "skyblocker.customItemNames.noItemUuid": "§b[§6Skyblocker§b] §cВы должны держать предмет, у которого есть uuid, чтобы задать пользовательское имя!", + "skyblocker.shortcuts.deleteWarning": "Сокращение '%s' будет потеряно навсегда! (Надолго!)", + "skyblocker.shortcuts.new": "Новое сокращение", + "skyblocker.customItemNames.unableToSetName": "§b[§6Skyblocker§b] §cНевозможно задать имя предмета :( (Вы на скайблоке?, у вас в руках предмет?)", + "skyblocker.shortcuts.command.replacement": "Замена команды", + "skyblocker.shortcuts.commandArg.tooltip": "Заменить одно или несколько слов/аргументов команды, содержащей несколько слов/аргументов, вместо того, чтобы сопоставлять всю команду.", + "skyblocker.shortcuts.notLoaded": "§c§ІСокращения еще не загружены", + "skyblocker.shortcuts.deleteQuestion": "Вы уверены, что хотите удалить это сокращение?", + "skyblocker.customItemNames.neverHad": "§b[§6Skyblocker§b] §fДанный предмет не имеет пользовательского названия, но почему бы его не добавить? ;)", + "skyblocker.customItemNames.added": "§b[§6Skyblocker§b] §fЗадайте собственное имя для удерживаемого предмета!", + "skyblocker.customItemNames.removed": "§b[§6Skyblocker§b] §fУдалено пользовательское имя этого предмета.", + "skyblocker.shortcuts.command.target": "Затронутая команда", + "skyblocker.shortcuts.commandArg.replacement": "Замена аргумента команды", + "skyblocker.shortcuts.commandArg.target": "Аргумент затронутой команды", + "skyblocker.customDyeColors.invalidHex": "§b[§6Skyblocker§b] §cНеверный HEX-код цвета!", + "skyblocker.customDyeColors.added": "§b[§6Skyblocker§b] §fУстановите цвет окраски для удерживаемого предмета!", + "skyblocker.customDyeColors.neverHad": "§b[§6Skyblocker§b] §fДанный предмет не имеет пользовательского набора цветов окраски, но почему бы его не добавить? ;)", + "skyblocker.customDyeColors.removed": "§b[§6Skyblocker§b] §fУдален пользовательский цвет окраски этого предмета.", + "skyblocker.customDyeColors.unableToSetColor": "§b[§6Skyblocker§b] §cНевозможно установить пользовательский цвет окраски :( (Вы на скайблоке?, у вас в руках предмет?)", + "skyblocker.customDyeColors.notDyeable": "§b[§6Skyblocker§b] §cЭтот предмет не является окрашиваемым предметом брони!", + "skyblocker.customDyeColors.noItemUuid": "§b[§6Skyblocker§b] §cВы должны держать предмет, у которого есть uuid, чтобы установить пользовательский цвет окраски!", + "skyblocker.customArmorTrims.removed": "§b[§6Skyblocker§b] §fУдалена пользовательская отделка брони этого предмета.", + "skyblocker.customArmorTrims.notAnArmorPiece": "§b[§6Skyblocker§b] §cЭтот предмет не является броней!", + "skyblocker.customArmorTrims.neverHad": "§b[§6Skyblocker§b] §fДанный предмет не имеет комплекта отделки брони, но почему бы его не добавить? ;)", + "skyblocker.customArmorTrims.added": "§b[§6Skyblocker§b] §fУстановите индивидуальную отделку брони для удерживаемого предмета!", + "skyblocker.customArmorTrims.invalidMaterialOrPattern": "§b[§6Skyblocker§b] §cВы предоставили либо недопустимый материал, либо недопустимый кузнечный шаблон!", + "skyblocker.customArmorTrims.unableToSetTrim": "§b[§6Skyblocker§b] §cНевозможно установить пользовательскую отделку брони :( (Вы на скайблоке?, у вас в руках предмет?)", + "skyblocker.customArmorTrims.noItemUuid": "§b[§6Skyblocker§b] §cВы должны держать предмет, у которого есть uuid, чтобы установить пользовательскую отделку брони!", + "text.autoconfig.skyblocker.option.general.itemTooltip.enableMuseumInfo.@Tooltip": "Если этот предмет можно пожертвовать музею, то покажется его категория (оружие, броня, инструменты, специальное). Также он покажет, был-ли отдан этот предмет музею, или нет (несовместимо с бесплатными).\n\nВключите API музея, чтобы информация была более точной!", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgroundStyle.@Tooltip": "На выбор есть круглый и квадратный фон редкости!", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgroundStyle": "Стиль фоновой редкости предмета", + "text.autoconfig.skyblocker.option.general.itemTooltip.enableExoticTooltip": "Включить подсказку редкости", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgrounds.@Tooltip": "Показывает цвет редкости предмата позади него(кроме обычного).", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgroundsOpacity": "Видимость фоновой редкости предмета", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgrounds": "Фоновый цвет редкости", + "text.autoconfig.skyblocker.option.general.itemProtection": "Предметная защита", + "text.autoconfig.skyblocker.option.general.itemProtection.slotLockStyle": "Стиль слота с закреплённым предметом", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra": "Куудра", + "text.autoconfig.skyblocker.option.general.dungeonQuality": "Данж-качество", + "text.autoconfig.skyblocker.option.general.dungeonQuality.@Tooltip": "Показывает качество и уровень дропа из данжа с мобов.\n\n\nПример:\nУр. 1-3 падает на 1-3 этажах\nУр. 4-7 падает на 4-7 этажах, или с 1-4 ур. Мастера\nУр. 8-10 падает только с 5-7 ур. Мастера", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.croesusProfit": "Подсчёт окупаемости сундука Croesus", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.croesusProfit.@Tooltip": "Подсвечивает сундук с самой лучшей окупаемостью у Croesus НИПа.\n\n\nСамый лучший сундук будет подсвечиваться зелёным цветом.\nЕсли для этого сундука нужен ключ данжа, то он будет подсвечиваться жёлтым", + "text.autoconfig.skyblocker.option.locations.dungeons.mapScreen": "Расположение карты и результата забега...", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.profitColor": "Прибыльный цвет", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.lossColor": "Убыточный цвет", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.neutralThreshold.@Tooltip": "Показывает порог нулевой окупаемости.", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.neutralColor": "Нейтральный цвет", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.enableProfitCalculator": "Включить калькулятор прибыли", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.includeKismet": "Включая цену Kismet", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.includeKismet.@Tooltip": "При включении, если вы использовали kismet, цена одного из них будет вычтена из прибыли", + "text.autoconfig.skyblocker.option.general.itemTooltip.enableExoticTooltip.@Tooltip": "Отображает тип экзотики под названием предмета, если предмет брони является экзотическим.", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.arrowPoisonThreshold.@Tooltip": "Если количество токсичного яда для стрел, которое есть у вас в инвентаре, ниже установленного порога, вы получите предупреждение.\n\n16 - это абсолютный минимум.\nВам нужно 32 для плавной фазы \"DPS\" с предварительным выстрелом.", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit": "Калькулятор прибыли от сундука в подземелье", + "text.autoconfig.skyblocker.option.locations.dungeons.solveTicTacToe.@Tooltip": "Помещает в красную рамку следующий лучший ход, который вы можете сделать!", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.dungeonScoreMessage.@Tooltip": "Сообщение, которое будет отправлено в чат при достижении показателя %d в подземельях. Строка \"[score]\" будет заменена на показатель подземелья (%d).", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableScoreHUD": "Включить HUD результатов", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableScoreHUD.@Tooltip": "Отображает результат прохождения подземелья в HUD.", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableScoreHUD.deathMessagesNote": "\n\n\nПримечание: Это корректно работает только в том случае, если сообщения о смерти включены в настройках вашего скайблока. Если вы хотите скрыть сообщения о смерти, используйте вместо этого параметр мода \"Hide Player Death Messages\", чтобы разрешить дальнейшую обработку сообщений о смерти.", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.enableProfitCalculator.@Tooltip": "Отображает прибыль от сундука подземелья в заголовке экрана сундука.\nЗеленый, если есть прибыль.\nКрасный, если прибыли нет.\nСерый, если вы ничего не получаете или теряете.\nСиний, если расчеты были основаны на неполных данных.", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.includeEssence.@Tooltip": "Отключение **не рекомендуется**, если вы забывчивый человек.", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.arrowPoisonThreshold": "Порог предупреждения о отравлении стрелой" } diff --git a/src/main/resources/assets/skyblocker/lang/tr_tr.json b/src/main/resources/assets/skyblocker/lang/tr_tr.json index 000bf1a3..258c52bb 100644 --- a/src/main/resources/assets/skyblocker/lang/tr_tr.json +++ b/src/main/resources/assets/skyblocker/lang/tr_tr.json @@ -38,7 +38,6 @@ "text.autoconfig.skyblocker.option.messages.hideMana": "Aksiyon barındaki mana tüketimlerini gizle", "text.autoconfig.skyblocker.option.messages.hideMana.@Tooltip": "FancyBar ile daha iyi bir deneyim sunar", "text.autoconfig.skyblocker.option.general.hideEmptyTooltips": "Menülerdeki boş eşya açıklamalarını gizle", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "Arka planı göster", "text.autoconfig.skyblocker.option.general.itemTooltip.avg.@Tooltip": "Kaç günlük ortalamanın gösterileceğini seçebilirsiniz", "text.autoconfig.skyblocker.option.general.itemTooltip.enableLowestBIN": "En düşük BIN fiyatını göster", "text.autoconfig.skyblocker.option.richPresence.enableRichPresence": "Aktif", diff --git a/src/main/resources/assets/skyblocker/lang/zh_cn.json b/src/main/resources/assets/skyblocker/lang/zh_cn.json index c5d3bccb..3451e7b2 100644 --- a/src/main/resources/assets/skyblocker/lang/zh_cn.json +++ b/src/main/resources/assets/skyblocker/lang/zh_cn.json @@ -64,15 +64,14 @@ "text.autoconfig.skyblocker.option.locations.dwarvenMines.solveFetchur": "解决Fetchur的迷题", "text.autoconfig.skyblocker.option.locations.dwarvenMines.solvePuzzler": "解决Puzzler的迷题", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud": "矮人矿井 HUD", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enableBackground": "启用背景", "text.autoconfig.skyblocker.category.messages": "消息", "text.autoconfig.skyblocker.option.messages.chatFilterResult.PASS": "禁用", "text.autoconfig.skyblocker.option.messages.chatFilterResult.FILTER": "启用", "text.autoconfig.skyblocker.option.messages.chatFilterResult.ACTION_BAR": "移动到动作栏", "text.autoconfig.skyblocker.option.messages.hideAbility": "隐藏技能冷却", "text.autoconfig.skyblocker.option.messages.hideHeal": "隐藏治疗消息", - "text.autoconfig.skyblocker.option.messages.hideAOTE": "隐藏瞬息之刃的提示消息", - "text.autoconfig.skyblocker.option.messages.hideImplosion": "隐藏核心爆裂技能的提示消息", + "text.autoconfig.skyblocker.option.messages.hideAOTE": "隐藏传送类能力的提示消息", + "text.autoconfig.skyblocker.option.messages.hideImplosion": "隐藏Implosion技能的提示消息", "text.autoconfig.skyblocker.option.messages.hideMoltenWave": "隐藏 Molten Wave 技能的提示消息", "text.autoconfig.skyblocker.option.messages.hideAds": "从公屏聊天中隐藏广告", "text.autoconfig.skyblocker.option.messages.hideTeleportPad": "隐藏传送点消息", @@ -98,8 +97,8 @@ "text.autoconfig.skyblocker.option.general.tabHud.tabHudScale.@Tooltip": "相对于原版 GUI 的百分比大小", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style": "HUD风格", "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[0]": "简约:仅显示委托及其进度百分比", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[1]": "精致:显示委托名,进度百分比与进度条以及图标", - "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[2]": "极简:仅在简单的方框内显示委托及其进度", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[1]": "\n精致:显示委托名,进度百分比与进度条以及图标", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[2]": "\n极简:仅在简单的方框内显示委托及其进度", "text.autoconfig.skyblocker.option.general.itemTooltip.enableMotesPrice": "启用 Motes 价格显示", "text.autoconfig.skyblocker.option.general.itemTooltip.enableMotesPrice.@Tooltip": "显示 Rift 中的物品售价,以 Mote 为单位。", "text.autoconfig.skyblocker.option.general.experiments": "实验台助手", @@ -109,10 +108,10 @@ "text.autoconfig.skyblocker.option.general.acceptReparty": "自动接受重新组队", "text.autoconfig.skyblocker.option.general.fairySouls": "仙女之魂助手", "text.autoconfig.skyblocker.option.general.fairySouls.enableFairySoulsHelper": "启用仙女之魂助手", - "skyblocker.fairySouls.markAllFound": "将当前岛屿上的全部仙女之魂标记为已发现", + "skyblocker.fairySouls.markAllFound": "§r将当前岛屿上的全部仙女之魂标记为已发现", "text.autoconfig.skyblocker.option.slayer.vampireSlayer.steakStakeUpdateFrequency.@Tooltip": "值越小,更新越频繁(可能会导致卡顿)", "text.autoconfig.skyblocker.option.general.shortcuts": "更精简的命令", - "text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts.@Tooltip": "使用 \"/skyblocker shortcuts\" 以编辑命令的精简版本, 以下选项必须至少启用之一方可有效. (此功能在空岛生存外也可使用)", + "text.autoconfig.skyblocker.option.general.shortcuts.enableShortcuts.@Tooltip": "使用“/skyblocker shortcuts”以编辑命令的精简版本, 以下选项必须至少启用之一方可有效(此功能在空岛生存外也可使用)。", "text.autoconfig.skyblocker.option.general.teleportOverlay": "传送类技能目标位置显示", "text.autoconfig.skyblocker.option.general.teleportOverlay.enableTeleportOverlays": "启用传送类技能目标位置显示", "text.autoconfig.skyblocker.option.general.teleportOverlay.enableWeirdTransmission": "启用 Weird Transmission 目标位置显示", @@ -160,7 +159,7 @@ "text.autoconfig.skyblocker.option.general.mythologicalRitual": "神话仪式助手", "text.autoconfig.skyblocker.option.general.mythologicalRitual.enableMythologicalRitualHelper": "开启神话仪式助手", "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enablePearlWaypoints": "启用珍珠路径点", - "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableAotvWaypoints": "启用瞬息之刃路径点", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableAotvWaypoints": "启用AOTV路径点", "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableFairySoulWaypoints": "启用仙女之魂路径点", "text.autoconfig.skyblocker.option.locations.spidersDen.relics": "遗物助手", "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreMessage": "启用地牢 %d 分数提示信息", @@ -183,5 +182,271 @@ "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableRoomMatching.@Tooltip": "关闭此选项可节省约20MB左右的内存,但是秘密路径点和§l部分谜题助手功能§r需要启用该选项", "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableItemWaypoints": "启用物品路径点", "text.autoconfig.skyblocker.option.general.quiverWarning.enableQuiverWarningAfterDungeon": "在地牢结束后启用箭袋提示", - "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableLeverWaypoints": "启用拉杆路径点" + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableLeverWaypoints": "启用拉杆路径点", + "key.skyblocker.toggleA": "将HUD标签页切换至显示屏A", + "key.skyblocker.toggleB": "将HUD标签页切换至显示屏B", + "text.autoconfig.skyblocker.option.general.itemProtection.slotLockStyle.@Tooltip": "选择精美或经典的锁定图标。", + "text.autoconfig.skyblocker.option.general.itemProtection": "物品保护", + "text.autoconfig.skyblocker.option.general.itemProtection.slotLockStyle": "物品栏锁定图标样式", + "text.autoconfig.skyblocker.option.general.tabHud.plainPlayerNames": "简洁的玩家名称", + "text.autoconfig.skyblocker.option.general.itemTooltip.enableMuseumInfo": "显示博物馆信息", + "text.autoconfig.skyblocker.option.general.enableTips": "启用提示", + "text.autoconfig.skyblocker.option.general.shortcuts.config": "设置精简命令", + "key.itemProtection": "保护物品", + "text.autoconfig.skyblocker.option.general.chestValue.enableChestValue.@Tooltip": "在容器中添加一个计算其价值的按钮。", + "text.autoconfig.skyblocker.option.general.chestValue.color": "箱子价值颜色", + "text.autoconfig.skyblocker.option.general.chestValue.enableChestValue": "启用箱子价值计算", + "text.autoconfig.skyblocker.option.general.specialEffects.rareDungeonDropEffects": "稀有地牢掉落效果", + "text.autoconfig.skyblocker.option.general.specialEffects": "特效", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.doorHighlightType.secretWaypointsNote": "\n\n\n注意:若使此功能生效,必须启用地牢秘密路径点。", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableScoreHUD.@Tooltip": "在状态栏显示地牢的分数。", + "text.autoconfig.skyblocker.option.general.dungeonQuality": "地牢物品品质", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableStonkWaypoints": "启用Stonk路径点", + "text.autoconfig.skyblocker.option.messages.hideToggleSkyMall": "隐藏Sky Mall切换的消息", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.screen": "矮人矿井HUD配置", + "text.autoconfig.skyblocker.option.messages.hideAOTE.@Tooltip": "隐藏烦人的“路径被阻挡”消息。", + "text.autoconfig.skyblocker.option.locations.dungeons.playerSecretsTracker.@Tooltip": "追踪玩家在地牢内找到的秘密数量。", + "text.autoconfig.skyblocker.option.locations.dungeons.playerSecretsTracker": "玩家解谜追踪器", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgroundStyle": "物品稀有度背景样式", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgroundStyle.@Tooltip": "选择圆形或方形背景样式!", + "text.autoconfig.skyblocker.option.locations.dungeons.lividColor.enableLividColorGlow": "启用Livid高亮", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.pearlWaypoints": "末影珍珠路径点", + "text.autoconfig.skyblocker.option.locations.dungeons.creeperSolver": "解决苦力怕激光谜题", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.enableDoorHighlight": "启用门的高亮", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight": "高亮门", + "text.autoconfig.skyblocker.option.general.titleContainer.@Tooltip": "用于同时显示多个标题,例如:吸血鬼杀手", + "text.autoconfig.skyblocker.option.locations.end": "终末之地", + "text.autoconfig.skyblocker.option.locations.end.hudEnabled": "启用HUD", + "text.autoconfig.skyblocker.option.general.flameOverlay.flameOpacity": "火焰不透明度", + "text.autoconfig.skyblocker.option.general.flameOverlay": "火焰叠加", + "text.autoconfig.skyblocker.option.general.flameOverlay.flameHeight": "火焰高度", + "text.autoconfig.skyblocker.option.locations.dungeons.mimicMessage.sendMimicMessage": "启用Mimic消息", + "text.autoconfig.skyblocker.option.locations.dungeons.mimicMessage": "Mimic消息", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreSound": "启用地牢分数%d的音效", + "text.autoconfig.skyblocker.option.general.chestValue.@Tooltip": "计算这个容器中的物品价值。", + "text.autoconfig.skyblocker.option.general.chestValue": "箱子价值", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreTitle": "启用地牢分数%d的标题", + "text.autoconfig.skyblocker.option.locations.dungeons.lividColor.enableLividColorTitle.@Tooltip": "在Livid的Boss战中显示Livid颜色的标题。", + "text.autoconfig.skyblocker.option.locations.dungeons.lividColor.enableLividColorTitle": "启用Livid颜色标题", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.lossColor": "亏损的颜色", + "text.autoconfig.skyblocker.option.quickNav.button.item.itemName": "物品ID", + "text.autoconfig.skyblocker.option.quickNav.button.item.count": "物品数量", + "text.autoconfig.skyblocker.option.locations.garden": "花园", + "text.autoconfig.skyblocker.option.locations.garden.dicerTitlePrevent": "阻止Dicer显示标题", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.enableDoorHighlight.@Tooltip": "分别用红色和绿色高亮上锁和已解锁的地牢大门。", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.doorHighlightType": "高亮类型", + "text.autoconfig.skyblocker.option.locations.dungeons.mimicMessage.mimicMessage": "Mimic消息", + "text.autoconfig.skyblocker.option.locations.dungeons.lividColor.enableLividColorGlow.@Tooltip": "为F5/M5的真Livid启用发光效果。", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.neutralColor": "中性的颜色", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.profitColor": "获利的颜色", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.showSecretText": "显示秘密文本", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgrounds": "物品稀有度背景", + "text.autoconfig.skyblocker.option.general.itemInfoDisplay.itemRarityBackgroundsOpacity": "物品稀有度背景不透明度", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.dungeonScoreMessage": "地牢分数%d消息", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.dungeonScoreMessage.@Tooltip": "当在地牢达到%d分数时,在聊天栏内发送信息。字符串“[score]”将替换为地牢分数(%d)。", + "text.autoconfig.skyblocker.option.quickNav.button.item": "物品", + "text.autoconfig.skyblocker.option.general.chestValue.incompleteColor.@Tooltip": "价格数据不完整时显示的颜色。", + "text.autoconfig.skyblocker.option.general.chestValue.incompleteColor": "不完整的颜色", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableScoreHUD": "启用分数状态栏", + "text.autoconfig.skyblocker.option.quickNav.button.item.nbt": "NBT", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enabledCommissions": "启用任务栏", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enabledPowder": "启用粉末栏", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud": "水晶洞窟地图", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.enabled": "启用", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.showLocations": "显示路径点", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsWaypoints.findInChat.@Tooltip": "在水晶洞窟时,读取聊天内容以查看是否有坐标,并将其提取出显示为路径点或在地图中标出", + "text.autoconfig.skyblocker.option.locations.end.screen": "终末之地HUD配置", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsWaypoints.findInChat": "在聊天栏中搜索路径点", + "text.autoconfig.skyblocker.option.messages.hideDeath": "隐藏玩家死亡信息", + "text.autoconfig.skyblocker.option.messages.hideMimicKill.@Tooltip": "过滤聊天中“Mimic dead!”和“Mimic killed!”的消息。", + "text.autoconfig.skyblocker.option.messages.hideMimicKill": "隐藏击杀Mimic的消息", + "text.autoconfig.skyblocker.option.locations.end.waypoint": "末地保护者路径点", + "text.autoconfig.skyblocker.option.locations.end.resetName": "重置已存储的末地统计信息", + "text.autoconfig.skyblocker.option.locations.end.resetText": "重置", + "text.autoconfig.skyblocker.option.messages.hideShowOff": "隐藏炫耀信息", + "text.autoconfig.skyblocker.option.messages.hideDeath.@Tooltip": "过滤聊天栏中玩家死亡的信息。", + "text.autoconfig.skyblocker.option.general.itemTooltip.enableMuseumInfo.@Tooltip": "如果该物品可捐赠给博物馆,则会显示该物品在博物馆中的类别。它还会显示一个标记,指示您是否已将该物品捐赠给您的博物馆(尚不支持免费赠品)。\n\n为了获得准确信息,请启用博物馆API!", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit": "地牢宝箱利润计算器", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsWaypoints": "水晶洞窟路径点", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsWaypoints.enabled": "启用路径点", + "text.autoconfig.skyblocker.option.general.waypoints.waypointType.@Tooltip": "路径点:显示高亮和信标光束。\n\n边框路径点:显示路径点和边框。\n\n高亮:只显示高亮。\n\n边框高亮:显示高亮和边框。\n\n边框:只显示边框。", + "text.autoconfig.skyblocker.option.general.searchOverlay": "搜索覆盖", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableBazaar": "为Bazaar启用", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableBazaar.@Tooltip": "在Bazaar中搜索时显示自定义搜索覆盖。", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableAuctionHouse": "为Auction House启用", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableAuctionHouse.@Tooltip": "在Auction House中搜索时显示自定义搜索覆盖。", + "text.autoconfig.skyblocker.option.general.searchOverlay.keepPreviousSearches": "保留上次搜索结果", + "text.autoconfig.skyblocker.option.general.searchOverlay.keepPreviousSearches.@Tooltip": "打开叠加层时保留现有搜索队列。", + "text.autoconfig.skyblocker.option.general.searchOverlay.maxSuggestions": "最大建议数", + "text.autoconfig.skyblocker.option.general.searchOverlay.maxSuggestions.@Tooltip": "要显示的建议项目的最大数量。", + "text.autoconfig.skyblocker.option.general.searchOverlay.historyLength": "保存的搜索历史长度", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableCommands": "从命令打开", + "text.autoconfig.skyblocker.option.general.searchOverlay.enableCommands.@Tooltip": "使用“/bzs”打开集市搜索,使用“/ahs”打开拍卖行。需要重新登录才能更新此设置。", + "text.autoconfig.skyblocker.option.general.searchOverlay.historyLabel": "历史记录:", + "text.autoconfig.skyblocker.option.locations.dungeons.doorHighlight.doorHighlightType.@Tooltip": "高亮:只显示高亮。\n\n边框+高亮:显示高亮与边框。\n\n边框:只显示边框。", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreTitle.@Tooltip": "当在地牢达到%d分数时显示标题。", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableDungeonScoreSound.@Tooltip": "当在地牢达到%d分数时播放音效。", + "text.autoconfig.skyblocker.option.locations.dungeons.mimicMessage.sendMimicMessage.@Tooltip": "杀死Mimic后在聊天中发送一条消息,以供其他玩家的分数计算模块使用。", + "text.autoconfig.skyblocker.option.messages.chatRules.screen": "聊天栏规则配置", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.modify": "修改", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.inputs": "输入:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.partialMatch": "允许部分匹配:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.partialMatch.@Tooltip": "过滤器是否可以匹配部分聊天消息。", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.ignoreCase.@Tooltip": "过滤器是否大小写敏感。", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.locations": "生效地点:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.regex": "是正则表达式:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.regex.@Tooltip": "过滤器使用正则表达式还是仅字符串。", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.ignoreCase": "忽略大小写:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.hideMessage.@Tooltip": "从聊天中移除这条信息。", + "skyblocker.shortcuts.new": "新的精简命令", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.outputs": "输出:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.hideMessage": "隐藏信息:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.actionBar.@Tooltip": "在操作栏中显示这条信息。", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.announcement.@Tooltip": "把这条信息显示在屏幕中间。", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.announcement": "显示公告:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.replace": "替代信息:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.finish": "完成", + "skyblocker.end.hud.zealotsTotalKills": "总击杀数:%d", + "skyblocker.end.hud.zealotsSinceLastEye": "自上个召唤之眼以来:%d", + "skyblocker.end.hud.protectorLocations.rightBack": "右后", + "skyblocker.quiverWarning.50Left": "你的箭袋里只剩50支箭了!", + "skyblocker.itemProtection.added": "§f你的%s已被保护!§o*你的物品感觉安全了些:')*", + "skyblocker.itemProtection.unableToProtect": "§c无法保护该物品:( (请检查自己是否在游玩空岛生存,以及是否手持物品。)", + "skyblocker.itemProtection.removed": "§f你的%s将§n不再受到保护!§f :( - §l小心一些!", + "skyblocker.tips.shortcuts": "使用 /skyblocker shortcuts 创建和编辑命令和消息快捷方式。", + "skyblocker.tips.discord": "请加入我们的Discord(https://discord.gg/aNNJHQykck)以了解 Skyblocker 的最新消息!", + "skyblocker.dungeons.secretsTracker.feedback": "%s§f找到了%s§f个秘密。%s", + "skyblocker.dungeons.secretsTracker.failFeedback": "§c无法计算此次关卡中玩家找到的秘密数量!", + "skyblocker.tips.protectItem": "使用 /skyblocker protectItem 防止意外掉落物品。", + "skyblocker.customItemNames.removed": "§f移除该物品的自定义名称。", + "skyblocker.partyFinder.loadingError": "如果你看到此内容超过5秒,可能是出现了什么错误……", + "skyblocker.partyFinder.partyCard.minClassLevel": "最低职业要求:%d", + "skyblocker.quiverWarning.10Left": "你的箭袋里只剩10支箭了!", + "skyblocker.tips.enabled": "§a启用提示。", + "skyblocker.tips.tip": "§a提示:%s\n", + "skyblocker.partyFinder.tabs.partyFinder": "组队查找器", + "text.autoconfig.skyblocker.option.messages.chatRules": "定义聊天规则", + "skyblocker.partyFinder.error.name": "队伍查找器错误!", + "skyblocker.partyFinder.error.message": "出现错误,将自动转回原版的队伍查找器", + "skyblocker.partyFinder.yourParty": "你的队伍", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.filter.@Tooltip": "与聊天消息匹配的字符串/正则表达式。", + "skyblocker.api.cache.MISS": "数据未缓存!", + "skyblocker.api.cache.HIT": "该数据已被缓存!\n已缓存%d秒。", + "skyblocker.shortcuts.deleteWarning": "精简命令“%s”将永远消失!(很长时间!)", + "skyblocker.quiverWarning.empty": "你的箭袋空了!", + "skyblocker.shortcuts.notLoaded": "§c§l精简命令尚未加载完毕", + "skyblocker.shortcuts.command.target": "目标命令", + "text.autoconfig.skyblocker.option.slayer.endermanSlayer": "[测试功能] 末影人杀手", + "text.autoconfig.skyblocker.option.slayer.vampireSlayer.effigyUpdateFrequency.@Tooltip": "值越低,更新越频繁,可能会导致卡顿。", + "skyblocker.shortcuts.commandArg.target": "目标命令参数", + "skyblocker.tips.clickNextTip": "§a[点击查看下一条提示]", + "skyblocker.tips.modMenuUpdate": "ModMenu 会通知你是否有适用于你的游戏版本的 Skyblocker 更新。", + "skyblocker.partyFinder.partyCard.minDungeonLevel": "最低地牢等级要求:%d", + "skyblocker.partyFinder.noParties": "未找到队伍。哭哭:(", + "skyblocker.end.hud.location": "位置:%s", + "skyblocker.customItemNames.noItemUuid": "§c你必须手持一个有uuid的物品才能为其设置自定义名称!", + "skyblocker.tips.disabled": "§a禁用提示。", + "skyblocker.tips.clickEnable": "§a[点击启用提示]", + "skyblocker.customItemNames.added": "§f为你当前所持物品设置自定义名称!", + "skyblocker.customItemNames.neverHad": "§f该物品还没有自定义名称,为什么不设置一个呢?;)", + "skyblocker.tips.customItemNames": "使用/skyblocker custom renameItem 自定义物品名称", + "skyblocker.tips.customArmorDyeColors": "使用 /skyblocker custom dyeColor 将自定义染料颜色应用到你的皮革护甲上", + "skyblocker.tips.helpCommand": "使用命令/skyblocker help,你可能会发现一些更炫酷的功能!", + "skyblocker.tips.quickNav": "你可以在配置中自定义 QuickNav 按钮。", + "skyblocker.tips.wikiLookup": "将鼠标悬停在某个物品上时按F4可在网页浏览器中打开其维基页面。", + "skyblocker.tips.fairySoulsEnigmaSoulsRelics": "不知道在哪里可以找到仙女之魂、Enigma之魂或遗物?让助手帮助你进行探索,他们会记住你已经找到了哪些灵魂。", + "skyblocker.customItemNames.unableToSetName": "§c无法设置自定义名称:( (请检查自己是否在游玩空岛生存,以及是否手持物品。)", + "text.autoconfig.skyblocker.option.messages.hideDicer.@Tooltip": "从聊天栏过滤Dicer信息。", + "text.autoconfig.skyblocker.option.slayer.endermanSlayer.highlightBeacons": "信标高亮", + "skyblocker.tips.customArmorTrims": "你可以使用/skyblocker custom armorTrim 为护甲设置自定义装饰。", + "skyblocker.itemProtection.noItemUuid": "§c你必须手持一个有uuid的物品才能为其施加保护!", + "skyblocker.tips.clickDisable": "§c[点击禁用提示]", + "skyblocker.tips.issues": "在 https://github.com/SkyblockerMod/Skyblocker 提交错误报告和功能请求。", + "skyblocker.tips.gallery": "浏览 https://hysky.de/skyblocker/gallery 查看该模组如何在游戏中工作!", + "skyblocker.tips.beta": "我们经常在 GitHub Actions 提供测试版,其中包含新的和实验性的功能。", + "skyblocker.partyFinder.deList": "点击取消列出", + "skyblocker.partyFinder.join": "点击加入", + "skyblocker.shortcuts.deleteQuestion": "你确定要移除这个精简命令吗?", + "skyblocker.dungeons.dungeonScore.scoreText": "分数:%s", + "skyblocker.tips.itemRarityBackground": "使用配置的物品信息显示部分中的物品稀有度背景功能轻松查看物品的稀有度。", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableDefaultWaypoints": "启用默认路径点", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableDefaultWaypoints.@Tooltip": "包括所有未分类的路径点。", + "skyblocker.relics.markAllFound": "§r将全部遗物标记为已发现", + "text.autoconfig.skyblocker.option.locations.dungeons.allowDroppingProtectedItems": "启用物品掉落保护", + "text.autoconfig.skyblocker.option.messages.hideDicer": "隐藏Dicer信息", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.new": "新聊天规则", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleName": "规则名称", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleEnabled": "规则已启用", + "skyblocker.end.hud.protectorLocations.left": "左", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.editRule": "编辑", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.editRule.@Tooltip": "打开规则配置。", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.deleteQuestion": "你确定要移除这条规则吗?", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.deleteWarning": "规则“%s”将永远消失!(很长时间!)", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen": "聊天规则配置", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.name": "名称:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.name.@Tooltip": "规则的名称。", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.filter": "过滤:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.true": "是", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.false": "否", + "skyblocker.end.hud.stage": "阶段:%s", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.actionBar": "在操作栏中显示:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.sounds": "播放音效:", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.sounds.@Tooltip": "当信息发送后播放音效。", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.sounds.none": "无", + "skyblocker.end.hud.protectorLocations.front": "前", + "skyblocker.end.hud.protectorLocations.center": "中央", + "skyblocker.end.hud.protectorLocations.back": "后", + "skyblocker.end.hud.protectorLocations.rightFront": "右前", + "skyblocker.fairySouls.markAllMissing": "§r将当前岛屿上的全部仙女之魂标记为已忽略", + "skyblocker.relics.markAllMissing": "§r将全部遗物标记为已忽略", + "skyblocker.shortcuts.config": "精简命令配置", + "skyblocker.shortcuts.command.replacement": "替代命令", + "skyblocker.shortcuts.commandArg.replacement": "替代命令参数", + "skyblocker.partyFinder.tabs.searchSettings": "搜索过滤器", + "skyblocker.partyFinder.tabs.createParty": "创建队伍", + "skyblocker.customArmorTrims.notAnArmorPiece": "§c该物品不是护甲!", + "text.autoconfig.skyblocker.option.messages.chatRules.screen.ruleScreen.locations.@Tooltip": "过滤器生效的地点列表。用“,”分隔各地点名称。如果希望它在除某个位置之外的任何地方都可以工作,使用“!”。地点名称:", + "skyblocker.end.hud.avgKillsPerEye": "平均每只眼所需击杀:%d", + "skyblocker.dungeons.puzzle.boulder.noSolution": "没有找到解法!", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.croesusProfit": "Croesus宝箱利润计算器", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.croesusProfit.@Tooltip": "高亮显示NPC Croesus处利润最高的宝箱。\n\n\n利润最高的宝箱将用绿色标识。\n如果有宝箱值得使用地牢钥匙,将使用黄色标识", + "skyblocker.dungeons.secrets.markSecretFound": "§r将秘密 #%d 标记为已找到。", + "text.autoconfig.skyblocker.option.locations.dungeons.solveSilverfish": "解决蠹虫谜题", + "text.autoconfig.skyblocker.option.locations.dungeons.solveIceFill": "解决冰块填充谜题", + "text.autoconfig.skyblocker.option.locations.dungeons.floor3GuardianHealthDisplay": "守卫者生命值显示(F3/M3)", + "text.autoconfig.skyblocker.option.locations.dungeons.solveWaterboard.@Tooltip": "单击带有绿色框的控制杆来解决谜题。", + "text.autoconfig.skyblocker.option.locations.dungeons.solveWaterboard": "解决水流引导谜题", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.supplyWaypoints": "补给路径点", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.suppliesAndFuelWaypointType": "补给/燃料路径点类型", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.fuelWaypoints": "燃料路径点", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.safeSpotWaypoints": "安全点路径", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.noArrowPoisonWarning": "箭毒耗尽警告", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.includeKismet.@Tooltip": "启用后,如果您使用 kismet,则将从利润中减去 kismet 的价格", + "text.autoconfig.skyblocker.option.general.titleContainer": "标题容器", + "text.autoconfig.skyblocker.option.general.titleContainer.titleContainerScale": "标题容器缩放", + "skyblocker.dungeons.secrets.markSecretMissing": "§r将秘密 #%d 标记为已忽略。", + "skyblocker.dungeons.secrets.physicalEntranceNotFound": "§c未找到地下城入口房间坐标。请返回绿色的入口房间。", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.noArrowPoisonWarning.@Tooltip": "在使用弓箭但没有箭毒时发出警告。只在DPS阶段有效。", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.arrowPoisonThreshold": "箭毒警告阈值", + "text.autoconfig.skyblocker.option.locations.crimsonIsle.kuudra.arrowPoisonThreshold.@Tooltip": "当背包中箭毒的数量低于设定的值时收到警告。", + "text.autoconfig.skyblocker.option.slayer.vampireSlayer.holyIceUpdateFrequency.@Tooltip": "值越低,更新越频繁,可能会导致高延迟。", + "text.autoconfig.skyblocker.option.locations.dungeons.floor3GuardianHealthDisplay.@Tooltip": "在F3/M3的Boss战中,在守卫者下方显示它们的生命值。", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableSuperboomWaypoints": "启用爆破路径点", + "skyblocker.crimson.kuudra.lowArrowPoison": "箭毒即将耗尽!", + "skyblocker.crimson.kuudra.noArrowPoison": "箭毒已耗尽!", + "text.autoconfig.skyblocker.option.locations.dungeons.creeperSolver.@Tooltip": "高亮显示最合适的光线路径与需要点击的目标。", + "text.autoconfig.skyblocker.option.general.titleContainer.config": "标题容器位置设置", + "skyblocker.dungeons.secrets.markSecretMissingUnable": "§c无法将秘密 #%d 标记为已忽略。", + "text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.mapScaling": "地图缩放", + "text.autoconfig.skyblocker.option.general.shortcuts.enableCommandArgShortcuts.@Tooltip": "精简命令是替换具有多个单词/参数的命令中一个或多个单词/参数的快捷方式。使用“/skyblocker shortcuts”编辑快捷方式。必须启用快捷方式才能生效。", + "text.autoconfig.skyblocker.option.locations.dungeons.solveBoulder": "解决推箱子谜题", + "text.autoconfig.skyblocker.option.locations.dungeons.solveBoulder.@Tooltip": "绘制路线并高亮按钮", + "text.autoconfig.skyblocker.option.locations.dungeons.mimicMessage.mimicMessage.@Tooltip": "杀死Mimic后将在聊天中发送的消息。建议保留默认值。", + "skyblocker.dungeons.secrets.markSecretFoundUnable": "§c无法将秘密 #%d 标记为已找到。", + "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableRoomMatching": "启用房间匹配", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.includeEssence.@Tooltip": "如果你健忘,**不建议**禁用。", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.enableScoreHUD.deathMessagesNote": "\n\n\n注意:仅当skyblock设置中启用了死亡消息时,此功能才会生效。如果想隐藏死亡消息,请使用此模组的隐藏玩家死亡消息设置来允许进一步处理死亡消息。", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonScore.scoreScaling": "分数缩放", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.enableProfitCalculator.@Tooltip": "在宝箱屏幕的标题中显示地牢宝箱的利润。\n如果获利则显示绿色。\n如果亏损则为红色。\n灰色表示没有获利也没有亏损。\n如果计算基于不完整的数据,则显示为蓝色。", + "text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.includeKismet": "包含 Kismet 价格" } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 461d5223..c5d05fed 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -41,6 +41,9 @@ "conflicts": { "immediatelyfast": "<=1.2.10+1.20.4" }, + "breaks": { + "forcecloseworldloadingscreen": "<=2.2.0" + }, "custom": { "modmenu": { "links": { diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json index fd7364ce..cc08ced8 100644 --- a/src/main/resources/skyblocker.mixins.json +++ b/src/main/resources/skyblocker.mixins.json @@ -36,9 +36,11 @@ "YggdrasilServicesKeyInfoMixin", "accessor.BeaconBlockEntityRendererInvoker", "accessor.DrawContextInvoker", + "accessor.EndermanEntityAccessor", "accessor.FrustumInvoker", "accessor.HandledScreenAccessor", "accessor.ItemStackAccessor", + "accessor.MessageHandlerAccessor", "accessor.PlayerListHudAccessor", "accessor.RecipeBookWidgetAccessor", "accessor.ScreenAccessor", |