diff options
author | Aaron <51387595+AzureAaron@users.noreply.github.com> | 2024-02-04 12:49:53 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-04 12:49:53 -0500 |
commit | fe1bc0589caef8ff9f2d616a3742e63e2668f00e (patch) | |
tree | 06e8e1b2ee3e3a9381dc042650f4fe6ac86582c5 /src/main/java/de | |
parent | ce90376c4a8a934cc4d2f8bc4dd0e5e1c71b3748 (diff) | |
parent | 71467890a61eb4e05793b1856f6303787216f2ec (diff) | |
download | Skyblocker-fe1bc0589caef8ff9f2d616a3742e63e2668f00e.tar.gz Skyblocker-fe1bc0589caef8ff9f2d616a3742e63e2668f00e.tar.bz2 Skyblocker-fe1bc0589caef8ff9f2d616a3742e63e2668f00e.zip |
Merge pull request #523 from olim88/crystal-hollows-fetures
Crystal hollows fetures
Diffstat (limited to 'src/main/java/de')
11 files changed, 861 insertions, 66 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index 3fca09ce..c11e4c86 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -13,6 +13,8 @@ import de.hysky.skyblocker.skyblock.dungeon.puzzle.TicTacToe; import de.hysky.skyblocker.skyblock.dungeon.puzzle.waterboard.Waterboard; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; import de.hysky.skyblocker.skyblock.dungeon.secrets.SecretsTracker; +import de.hysky.skyblocker.skyblock.dwarven.CrystalsHud; +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.item.*; @@ -99,6 +101,8 @@ public class SkyblockerMod implements ClientModInitializer { QuickNav.init(); ItemCooldowns.init(); DwarvenHud.init(); + CrystalsHud.init(); + CrystalsLocationsManager.init(); ChatMessageListener.init(); Shortcuts.init(); DiscordRPCManager.init(); @@ -142,6 +146,8 @@ public class SkyblockerMod implements ClientModInitializer { Scheduler.INSTANCE.scheduleCyclic(LividColor::update, 10); 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/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java index a7569adb..4acb8064 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java @@ -873,11 +873,20 @@ public class SkyblockerConfig { @SerialEntry public DwarvenHud dwarvenHud = new DwarvenHud(); + + @SerialEntry + public CrystalsHud crystalsHud = new CrystalsHud(); + + @SerialEntry + public CrystalsWaypoints crystalsWaypoints = new CrystalsWaypoints(); } public static class DwarvenHud { @SerialEntry - public boolean enabled = true; + public boolean enabledCommissions = true; + + @SerialEntry + public boolean enabledPowder = true; @SerialEntry public DwarvenHudStyle style = DwarvenHudStyle.SIMPLE; @@ -890,6 +899,40 @@ public class SkyblockerConfig { @SerialEntry public int y = 10; + + @SerialEntry + public int powderX = 10; + + @SerialEntry + public int powderY = 70; + } + + public static class CrystalsHud { + @SerialEntry + public boolean enabled = true; + + @SerialEntry + public boolean showLocations = true; + + @SerialEntry + public int locationSize = 8; + + @SerialEntry + public int x = 10; + + @SerialEntry + public int y = 130; + + @SerialEntry + public float mapScaling = 1f; + } + + public static class CrystalsWaypoints { + @SerialEntry + public boolean enabled = true; + + @SerialEntry + public boolean findInChat = true; } public enum DwarvenHudStyle { 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 80d6485b..97b48bc4 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/DwarvenMinesCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/DwarvenMinesCategory.java @@ -2,12 +2,15 @@ package de.hysky.skyblocker.config.categories; import de.hysky.skyblocker.config.ConfigUtils; import de.hysky.skyblocker.config.SkyblockerConfig; +import de.hysky.skyblocker.skyblock.dwarven.CrystalsHudConfigScreen; import dev.isxander.yacl3.api.ButtonOption; import dev.isxander.yacl3.api.ConfigCategory; import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.OptionDescription; import dev.isxander.yacl3.api.OptionGroup; import de.hysky.skyblocker.skyblock.dwarven.DwarvenHudConfigScreen; +import dev.isxander.yacl3.api.controller.FloatFieldControllerBuilder; +import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; import net.minecraft.client.MinecraftClient; import net.minecraft.text.Text; @@ -45,15 +48,22 @@ public class DwarvenMinesCategory { .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud")) .collapsed(false) .option(Option.<Boolean>createBuilder() - .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enabled")) - .binding(defaults.locations.dwarvenMines.dwarvenHud.enabled, - () -> config.locations.dwarvenMines.dwarvenHud.enabled, - newValue -> config.locations.dwarvenMines.dwarvenHud.enabled = newValue) + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enabledCommissions")) + .binding(defaults.locations.dwarvenMines.dwarvenHud.enabledCommissions, + () -> config.locations.dwarvenMines.dwarvenHud.enabledCommissions, + newValue -> config.locations.dwarvenMines.dwarvenHud.enabledCommissions = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.enabledPowder")) + .binding(defaults.locations.dwarvenMines.dwarvenHud.enabledPowder, + () -> config.locations.dwarvenMines.dwarvenHud.enabledPowder, + newValue -> config.locations.dwarvenMines.dwarvenHud.enabledPowder = newValue) .controller(ConfigUtils::createBooleanController) .build()) .option(Option.<SkyblockerConfig.DwarvenHudStyle>createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style")) - .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[0]"), + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[0]"), Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[1]"), Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.dwarvenHud.style.@Tooltip[2]"))) .binding(defaults.locations.dwarvenMines.dwarvenHud.style, @@ -74,6 +84,68 @@ public class DwarvenMinesCategory { .controller(ConfigUtils::createBooleanController) .build()) .build()) + //crystal HUD + .group(OptionGroup.createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud")) + .collapsed(false) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.enabled")) + .binding(defaults.locations.dwarvenMines.crystalsHud.enabled, + () -> config.locations.dwarvenMines.crystalsHud.enabled, + newValue -> config.locations.dwarvenMines.crystalsHud.enabled = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(ButtonOption.createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.screen")) + .text(Text.translatable("text.skyblocker.open")) + .action((screen, opt) -> MinecraftClient.getInstance().setScreen(new CrystalsHudConfigScreen(screen))) + .build()) + .option(Option.<Float>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.mapScaling")) + .binding(defaults.locations.dwarvenMines.crystalsHud.mapScaling, + () -> config.locations.dwarvenMines.crystalsHud.mapScaling, + newValue -> config.locations.dwarvenMines.crystalsHud.mapScaling = newValue) + .controller(FloatFieldControllerBuilder::create) + .build()) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.showLocations")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.showLocations.@Tooltip"))) + .binding(defaults.locations.dwarvenMines.crystalsHud.showLocations, + () -> config.locations.dwarvenMines.crystalsHud.showLocations, + newValue -> config.locations.dwarvenMines.crystalsHud.showLocations = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Integer>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.showLocations.locationSize")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsHud.showLocations.locationSize.@Tooltip"))) + .binding(defaults.locations.dwarvenMines.crystalsHud.locationSize, + () -> config.locations.dwarvenMines.crystalsHud.locationSize, + newValue -> config.locations.dwarvenMines.crystalsHud.locationSize = newValue) + .controller(opt -> IntegerSliderControllerBuilder.create(opt).range(4, 12).step(2)) + .build()) + .build()) + //crystals waypoints + .group(OptionGroup.createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsWaypoints")) + .collapsed(false) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsWaypoints.enabled")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsWaypoints.enabled.@Tooltip"))) + .binding(defaults.locations.dwarvenMines.crystalsWaypoints.enabled, + () -> config.locations.dwarvenMines.crystalsWaypoints.enabled, + newValue -> config.locations.dwarvenMines.crystalsWaypoints.enabled = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsWaypoints.findInChat")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dwarvenMines.crystalsWaypoints.findInChat.@Tooltip"))) + .binding(defaults.locations.dwarvenMines.crystalsWaypoints.findInChat, + () -> config.locations.dwarvenMines.crystalsWaypoints.findInChat, + newValue -> config.locations.dwarvenMines.crystalsWaypoints.findInChat = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + + .build()) .build(); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java new file mode 100644 index 00000000..7b15c61e --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java @@ -0,0 +1,164 @@ +package de.hysky.skyblocker.skyblock.dwarven; + +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; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +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 java.awt.*; +import java.util.Arrays; +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" }; + + public static boolean visible = false; + + public static void init() { + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") + .then(ClientCommandManager.literal("hud") + .then(ClientCommandManager.literal("crystals") + .executes(Scheduler.queueOpenScreenCommand(CrystalsHudConfigScreen::new)))))); + + HudRenderCallback.EVENT.register((context, tickDelta) -> { + if (!SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.enabled + || CLIENT.player == null + || !visible) { + return; + } + render(context, tickDelta, SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.x, + SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.y); + }); + } + + protected static IntIntPair getDimensionsForConfig() { + int size = (int) (62 * SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.mapScaling); + return IntIntPair.of(size, size); + } + + + /** + * Renders the map to the players UI. renders the background image ({@link CrystalsHud#MAP_TEXTURE}) of the map then if enabled special locations on the map. then finally the player to the map. + * + * @param context DrawContext to draw map to + * @param tickDelta For interpolating the player's yaw for map marker + * @param hudX Top left X coordinate of the map + * @param hudY Top left Y coordinate of the map + */ + private static void render(DrawContext context, float tickDelta, int hudX, int hudY) { + float scale = SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.mapScaling; + + //make sure the map renders infront of some stuff - improve this in the future with better layering (1.20.5?) + //and set position and scale + MatrixStack matrices = context.getMatrices(); + matrices.push(); + matrices.translate(hudX, hudY, 200f); + matrices.scale(scale, scale, 0f); + + //draw map texture + context.drawTexture(MAP_TEXTURE, 0, 0, 0, 0, 62, 62, 62, 62); + + //if enabled add waypoint locations to map + if (SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.showLocations) { + Map<String,CrystalsWaypoint> ActiveWaypoints = CrystalsLocationsManager.activeWaypoints; + + for (CrystalsWaypoint waypoint : ActiveWaypoints.values()) { + Color waypointColor = waypoint.category.color; + 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; + } + + //fill square of size locationSize around the coordinates of the location + context.fill(renderPos.x() - locationSize / 2, renderPos.y() - locationSize / 2, renderPos.x() + locationSize / 2, renderPos.y() + locationSize / 2, waypointColor.getRGB()); + } + } + + //draw player on map + if (CLIENT.player == null || CLIENT.getNetworkHandler() == null) { + return; + } + + //get player location + double playerX = CLIENT.player.getX(); + double playerZ = CLIENT.player.getZ(); + float playerRotation = CLIENT.player.getYaw(); //TODO make the transitions more rough? + Vector2ic renderPos = transformLocation(playerX, playerZ); + + int renderX = renderPos.x() - 2; + int renderY = renderPos.y() - 3; + + //position, scale and rotate the player marker + matrices.translate(renderX, renderY, 0f); + matrices.scale(0.75f, 0.75f, 0f); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(yaw2Cardinal(playerRotation)), 2.5f, 3.5f, 0); + + //draw marker on map + context.drawTexture(MAP_ICON, 0, 0, 2, 0, 5, 7, 128, 128); + + //todo add direction (can not work out how to rotate) + matrices.pop(); + } + + /** + * Converts an X and Z coordinate in the crystal hollow to a X and Y coordinate on the map. + * + * @param x the world X coordinate + * @param z the world Z coordinate + * @return a vector representing the x and y values + */ + protected static Vector2ic transformLocation(double x, double z) { + //converts an x and z to a location on the map + int transformedX = (int) ((x - 202) / 621 * 62); + int transformedY = (int) ((z - 202) / 621 * 62); + transformedX = MathHelper.clamp(transformedX, 0, 62); + transformedY = MathHelper.clamp(transformedY, 0, 62); + + return new Vector2i(transformedX, transformedY); + } + + /** + * Converts yaw to the cardinal directions that a player marker can be rotated towards on a map. + * The rotations of a marker follow this order: N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW. + * <br><br> + * 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); + + return (clipped * 360f) / 16f; + } + + /** + * Works out if the crystals map should be rendered and sets {@link CrystalsHud#visible} accordingly. + * + */ + public static void update() { + if (CLIENT.player == null || CLIENT.getNetworkHandler() == null || !SkyblockerConfigManager.get().locations.dwarvenMines.crystalsHud.enabled) { + visible = false; + return; + } + + //get if the player is in the crystals + visible = Utils.isInCrystalHollows(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHudConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHudConfigScreen.java new file mode 100644 index 00000000..b4e423e9 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHudConfigScreen.java @@ -0,0 +1,69 @@ +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 net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; + +import java.awt.*; + +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; + + 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()); + } + + @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); + } + + @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); + } + + 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); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java new file mode 100644 index 00000000..0a4e4518 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java @@ -0,0 +1,195 @@ +package de.hysky.skyblocker.skyblock.dwarven; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.logging.LogUtils; + +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.utils.Constants; +import de.hysky.skyblocker.utils.Utils; +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; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.command.argument.BlockPosArgumentType; +import net.minecraft.command.argument.PosArgument; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.math.BlockPos; + +import java.awt.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.slf4j.Logger; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; + +public class CrystalsLocationsManager { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); + + /** + * 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 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() { + WorldRenderEvents.AFTER_TRANSLUCENT.register(CrystalsLocationsManager::render); + ClientReceiveMessageEvents.GAME.register(CrystalsLocationsManager::extractLocationFromMessage); + ClientCommandRegistrationCallback.EVENT.register(CrystalsLocationsManager::registerWaypointLocationCommands); + ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> reset()); + } + + private static void extractLocationFromMessage(Text message, Boolean overlay) { + if (!SkyblockerConfigManager.get().locations.dwarvenMines.crystalsWaypoints.findInChat || !Utils.isInCrystalHollows()) { + return; + } + + try { + //get the message text + String value = message.getString(); + Matcher matcher = TEXT_CWORDS_PATTERN.matcher(value); + //if there are coordinates in the message try to get them and what they are talking about + if (matcher.find()) { + String location = matcher.group(); + int[] coordinates = Arrays.stream(location.split(" ", 3)).mapToInt(Integer::parseInt).toArray(); + BlockPos blockPos = new BlockPos(coordinates[0], coordinates[1], coordinates[2]); + + //if position is not in the hollows do not add it + if (!checkInCrystals(blockPos)) { + return; + } + + //see if there is a name of a location to add to this + 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); + return; + } + } + + //if the location is not found ask the user for the location (could have been in a previous chat message) + if (CLIENT.player == null || CLIENT.getNetworkHandler() == null) { + return; + } + + CLIENT.player.sendMessage(getLocationInputText(location), false); + } + } catch (Exception e) { + LOGGER.error("[Skyblocker Crystals Locations Manager] Encountered an exception while extracing a location from a chat message!", e); + } + } + protected static Boolean checkInCrystals(BlockPos pos){ + //checks if a location is inside crystal hollows bounds + return pos.getX() >= 202 && pos.getX() <= 823 + && pos.getZ() >= 202 && pos.getZ() <= 823 + && pos.getY() >= 31 && pos.getY() <= 188; + } + + private static void registerWaypointLocationCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) { + dispatcher.register(literal(SkyblockerMod.NAMESPACE) + .then(literal("crystalWaypoints") + .then(argument("pos", BlockPosArgumentType.blockPos()) + .then(argument("place", StringArgumentType.greedyString()) + .executes(context -> addWaypointFromCommand(context.getSource(), getString(context, "place"), context.getArgument("pos", PosArgument.class))) + ) + ) + ) + ); + } + + protected static Text getSetLocationMessage(String location,BlockPos blockPos) { + MutableText text = Constants.PREFIX.get(); + text.append(Text.literal("Added waypoint for ")); + Color locationColor = WAYPOINT_LOCATIONS.get(location).color; + text.append(Text.literal(location).withColor(locationColor.getRGB())); + text.append(Text.literal(" at : " + blockPos.getX() + " " + blockPos.getY() + " " + blockPos.getZ() + ".")); + + return text; + } + + private static Text getLocationInputText(String location) { + MutableText text = Constants.PREFIX.get(); + + for (String waypointLocation : WAYPOINT_LOCATIONS.keySet()) { + Color locationColor = WAYPOINT_LOCATIONS.get(waypointLocation).color; + text.append(Text.literal("[" + waypointLocation + "]").withColor(locationColor.getRGB()).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/skyblocker crystalWaypoints " + location + " " + waypointLocation)))); + } + + return text; + } + + public static int addWaypointFromCommand(FabricClientCommandSource source, String place, PosArgument location) { + // TODO Less hacky way with custom ClientBlockPosArgumentType + 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); + + //tell the client it has done this + if (CLIENT.player == null || CLIENT.getNetworkHandler() == null) { + return 0; + } + + CLIENT.player.sendMessage(getSetLocationMessage(place, blockPos), false); + } + + return Command.SINGLE_SUCCESS; + } + + + 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); + } + + public static void render(WorldRenderContext context) { + if (SkyblockerConfigManager.get().locations.dwarvenMines.crystalsWaypoints.enabled) { + for (CrystalsWaypoint crystalsWaypoint : activeWaypoints.values()) { + if (crystalsWaypoint.shouldRender()) { + crystalsWaypoint.render(context); + } + } + } + } + + private static void reset() { + activeWaypoints.clear(); + } + + public static void update() { + if (CLIENT.player == null || CLIENT.getNetworkHandler() == null || !SkyblockerConfigManager.get().locations.dwarvenMines.crystalsWaypoints.enabled || !Utils.isInCrystalHollows()) { + return; + } + + //get if the player is in the crystals + String location = Utils.getIslandArea().replace("⏣ ", ""); + //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); + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsWaypoint.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsWaypoint.java new file mode 100644 index 00000000..fbb43083 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsWaypoint.java @@ -0,0 +1,98 @@ +package de.hysky.skyblocker.skyblock.dwarven; + +import de.hysky.skyblocker.config.SkyblockerConfig; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.utils.render.RenderHelper; +import de.hysky.skyblocker.utils.waypoint.Waypoint; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.text.Text; +import net.minecraft.util.DyeColor; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +import java.awt.*; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.function.ToDoubleFunction; + +public class CrystalsWaypoint extends Waypoint { + private static final Supplier<SkyblockerConfig.Waypoints> CONFIG = () -> SkyblockerConfigManager.get().general.waypoints; + private static final Supplier<Type> TYPE_SUPPLIER = () -> CONFIG.get().waypointType; + final Category category; + final Text name; + private final Vec3d centerPos; + + CrystalsWaypoint(Category category, Text name, BlockPos pos) { + super(pos, TYPE_SUPPLIER, category.colorComponents); + this.category = category; + this.name = name; + this.centerPos = pos.toCenterPos(); + } + + static ToDoubleFunction<CrystalsWaypoint> getSquaredDistanceToFunction(Entity entity) { + return crystalsWaypoint -> entity.squaredDistanceTo(crystalsWaypoint.centerPos); + } + + static Predicate<CrystalsWaypoint> getRangePredicate(Entity entity) { + return crystalsWaypoint -> entity.squaredDistanceTo(crystalsWaypoint.centerPos) <= 36D; + } + + @Override + public boolean shouldRender() { + return super.shouldRender() ; + } + + @Override + public boolean equals(Object obj) { + return super.equals(obj) || obj instanceof CrystalsWaypoint other && category == other.category && name.equals(other.name) && pos.equals(other.pos); + } + + /** + * Renders the secret waypoint, including a waypoint through {@link Waypoint#render(WorldRenderContext)}, the name, and the distance from the player. + */ + @Override + public void render(WorldRenderContext context) { + super.render(context); + + Vec3d posUp = centerPos.add(0, 1, 0); + RenderHelper.renderText(context, name, posUp, true); + double distance = context.camera().getPos().distanceTo(centerPos); + RenderHelper.renderText(context, Text.literal(Math.round(distance) + "m").formatted(Formatting.YELLOW), posUp, 1, MinecraftClient.getInstance().textRenderer.fontHeight + 1, true); + + } + + /** + * enum for the different waypoints used int the crystals hud each with a {@link Category#name} and associated {@link Category#color} + */ + enum Category { + JUNGLE_TEMPLE("Jungle Temple", new Color(DyeColor.PURPLE.getSignColor())), + MINES_OF_DIVAN("Mines of Divan", Color.GREEN), + GOBLIN_QUEENS_DEN("Goblin Queen's Den", new Color(DyeColor.ORANGE.getSignColor())), + LOST_PRECURSOR_CITY("Lost Precursor City", Color.CYAN), + KHAZAD_DUM("Khazad-dûm", Color.YELLOW), + FAIRY_GROTTO("Fairy Grotto", Color.PINK), + DRAGONS_LAIR("Dragon's Lair", Color.BLACK), + CORLEONE("Corleone", Color.WHITE), + KING_YOLKAR("King Yolkar", Color.RED), + ODAWA("Odawa", Color.MAGENTA), + KEY_GUARDIAN("Key Guardian", Color.LIGHT_GRAY); + + public final Color color; + private final String name; + private final float[] colorComponents; + + Category(String name,Color color) { + this.name = name; + this.color = color; + this.colorComponents = color.getColorComponents(null); + } + + @Override + public String toString() { + return name; + } + } +} 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 6fa03816..4446c1a7 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java @@ -3,7 +3,10 @@ package de.hysky.skyblocker.skyblock.dwarven; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.tabhud.util.Colors; 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; @@ -25,6 +28,9 @@ public class DwarvenHud { public static final MinecraftClient client = MinecraftClient.getInstance(); public static List<Commission> commissionList = new ArrayList<>(); + public static String mithrilPowder = "0"; + public static String gemStonePowder = "0"; + public static final List<Pattern> COMMISSIONS = Stream.of( "(?:Titanium|Mithril|Hard Stone) Miner", "(?:Ice Walker|Golden Goblin|(?<!Golden )Goblin|Goblin Raid|Automaton|Sludge|Team Treasurite Member|Yog|Boss Corleone|Thyst) Slayer", @@ -39,6 +45,8 @@ public class DwarvenHud { "(?:Amber|Sapphire|Jade|Amethyst|Topaz) Crystal Hunter", "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,]+"); public static void init() { ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(ClientCommandManager.literal("skyblocker") @@ -47,94 +55,162 @@ public class DwarvenHud { .executes(Scheduler.queueOpenScreenCommand(DwarvenHudConfigScreen::new)))))); HudRenderCallback.EVENT.register((context, tickDelta) -> { - if (!SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabled + if ((!SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledCommissions && !SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) || client.options.playerListKey.isPressed() || client.player == null - || commissionList.isEmpty()) { + || (!Utils.isInDwarvenMines() && !Utils.isInCrystalHollows())) { return; } - render(HudCommsWidget.INSTANCE, context, SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.x, - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.y, commissionList); + + render(HudCommsWidget.INSTANCE, HudPowderWidget.INSTANCE, context, + SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.x, + SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.y, + SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.powderX, + SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.powderY, + commissionList); }); } - public static IntIntPair getDimForConfig(List<Commission> commissions) { + /** + * 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 IntIntPair.of( - HudCommsWidget.INSTANCE_CFG.getWidth(), - HudCommsWidget.INSTANCE_CFG.getHeight()); + 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 IntIntPair.of( - HudCommsWidget.INSTANCE_CFG.getWidth(), - HudCommsWidget.INSTANCE_CFG.getHeight()); + yield Pair.of( + IntIntPair.of( + HudCommsWidget.INSTANCE_CFG.getWidth(), + HudCommsWidget.INSTANCE_CFG.getHeight()), + IntIntPair.of( + HudPowderWidget.INSTANCE_CFG.getWidth(), + HudPowderWidget.INSTANCE_CFG.getHeight()) + ); } - default -> IntIntPair.of(200, 20 * commissions.size()); + default -> Pair.of( + IntIntPair.of( + 200, + 20 * commissions.size()), + IntIntPair.of( + 200, + 40) + ); }; } - public static void render(HudCommsWidget hcw, DrawContext context, int hudX, int hudY, List<Commission> commissions) { + 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, context, hudX, hudY, commissions); - case FANCY -> renderFancy(hcw, context, hudX, hudY, commissions); - case CLASSIC -> renderClassic(context, hudX, hudY, 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); } } - public static void renderClassic(DrawContext context, int hudX, int hudY, List<Commission> commissions) { + /** + * Renders hud to window without using the widget rendering + * @param context DrawContext to draw the hud to + * @param comHudX X coordinate of the commissions hud + * @param comHudY Y coordinate of the commissions hud + * @param powderHudX X coordinate of the powder hud + * @param powderHudY Y coordinate of the powder hud + * @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) { - context.fill(hudX, hudY, hudX + 200, hudY + (20 * commissions.size()), 0x64000000); + 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) { + int y = 0; + for (Commission commission : commissions) { + float percentage; + if (!commission.progression().contains("DONE")) { + percentage = Float.parseFloat(commission.progression().substring(0, commission.progression().length() - 1)); + } else { + percentage = 100f; + } - int y = 0; - for (Commission commission : commissions) { - float percentage; - if (!commission.progression().contains("DONE")) { - percentage = Float.parseFloat(commission.progression().substring(0, commission.progression().length() - 1)); - } else { - percentage = 100f; + context + .drawTextWithShadow(client.textRenderer, + Text.literal(commission.commission + ": ").formatted(Formatting.AQUA) + .append(Text.literal(commission.progression).formatted(Colors.hypixelProgressColor(percentage))), + comHudX + 5, comHudY + y + 5, 0xFFFFFFFF); + y += 20; } - + } + if(SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) { + //render mithril powder then gemstone + context + .drawTextWithShadow(client.textRenderer, + Text.literal("Mithril: " + mithrilPowder).formatted(Formatting.AQUA), + powderHudX + 5, powderHudY + 5, 0xFFFFFFFF); context .drawTextWithShadow(client.textRenderer, - Text.literal(commission.commission + ": ") - .styled(style -> style.withColor(Formatting.AQUA)) - .append(Text.literal(commission.progression) - .styled(style -> style.withColor(Colors.hypixelProgressColor(percentage)))), - hudX + 5, hudY + y + 5, 0xFFFFFFFF); - y += 20; + Text.literal("Gemstone: " + gemStonePowder).formatted(Formatting.DARK_PURPLE), + powderHudX + 5, powderHudY + 25, 0xFFFFFFFF); } } - public static void renderSimple(HudCommsWidget hcw, DrawContext context, int hudX, int hudY, List<Commission> commissions) { - hcw.updateData(commissions, false); - hcw.update(); - hcw.setX(hudX); - hcw.setY(hudY); - hcw.render(context, - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + 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) { + hcw.updateData(commissions, false); + hcw.update(); + hcw.setX(comHudX); + hcw.setY(comHudY); + hcw.render(context, + SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + } + if (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) { + hpw.update(); + hpw.setX(powderHudX); + hpw.setY(powderHudY); + hpw.render(context, + SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + } } - public static void renderFancy(HudCommsWidget hcw, DrawContext context, int hudX, int hudY, List<Commission> commissions) { - hcw.updateData(commissions, true); - hcw.update(); - hcw.setX(hudX); - hcw.setY(hudY); - hcw.render(context, - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + 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) { + hcw.updateData(commissions, true); + hcw.update(); + hcw.setX(comHudX); + hcw.setY(comHudY); + hcw.render(context, + SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + } + if (SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledPowder) { + hpw.update(); + hpw.setX(powderHudX); + hpw.setY(powderHudY); + hpw.render(context, + SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enableBackground); + } } public static void update() { - commissionList = new ArrayList<>(); - if (client.player == null || client.getNetworkHandler() == null || !SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabled) + if (client.player == null || client.getNetworkHandler() == null || !SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.enabledCommissions || (!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()) { @@ -142,6 +218,15 @@ public class DwarvenHud { } } + //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]; + } } }); } 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 6f281ba9..d5dc19f2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHudConfigScreen.java @@ -3,7 +3,9 @@ package de.hysky.skyblocker.skyblock.dwarven; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.dwarven.DwarvenHud.Commission; 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 net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; @@ -15,9 +17,11 @@ import java.util.List; public class DwarvenHudConfigScreen extends Screen { 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 hudX = SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.x; - private int hudY = 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() { @@ -33,16 +37,20 @@ public class DwarvenHudConfigScreen extends Screen { 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, context, hudX, hudY, List.of(new DwarvenHud.Commission("Test Commission 1", "1%"), new DwarvenHud.Commission("Test Commission 2", "2%"))); + 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()); } @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - IntIntPair dims = DwarvenHud.getDimForConfig(CFG_COMMS); - if (RenderHelper.pointIsInArea(mouseX, mouseY, hudX, hudY, hudX + 200, hudY + 40) && 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); + 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); } @@ -50,17 +58,21 @@ public class DwarvenHudConfigScreen extends Screen { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (button == 1) { - IntIntPair dims = DwarvenHud.getDimForConfig(CFG_COMMS); - hudX = this.width / 2 - dims.leftInt(); - hudY = this.height / 2 - dims.rightInt(); + 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); } @Override public void close() { - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.x = hudX; - SkyblockerConfigManager.get().locations.dwarvenMines.dwarvenHud.y = hudY; + 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); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/hud/HudPowderWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/hud/HudPowderWidget.java new file mode 100644 index 00000000..1d11c2a6 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/hud/HudPowderWidget.java @@ -0,0 +1,40 @@ +package de.hysky.skyblocker.skyblock.tabhud.widget.hud; + +import de.hysky.skyblocker.skyblock.tabhud.util.Ico; +import de.hysky.skyblocker.skyblock.tabhud.widget.Widget; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +// this widget shows the status of the king's commissions. +// (dwarven mines and crystal hollows) +// USE ONLY WITH THE DWARVEN HUD! + +public class HudPowderWidget extends Widget { + + private static final MutableText TITLE = Text.literal("Powders").formatted(Formatting.DARK_AQUA, + Formatting.BOLD); + + + // disgusting hack to get around text renderer issues. + // the ctor eventually tries to get the font's height, which doesn't work + // when called before the client window is created (roughly). + // the rebdering god 2 from the fabricord explained that detail, thanks! + //coppied from the HodCommsWidget to be used in the same place + public static final HudPowderWidget INSTANCE = new HudPowderWidget(); + public static final HudPowderWidget INSTANCE_CFG = new HudPowderWidget(); + + // another repulsive hack to make this widget-like hud element work with the new widget class + // DON'T USE WITH THE WIDGET SYSTEM, ONLY USE FOR DWARVENHUD! + public HudPowderWidget() { + super(TITLE, Formatting.DARK_AQUA.getColorValue()); + } + + + @Override + public void updateContent() { + this.addSimpleIcoText(Ico.MITHRIL, "Mithril:", Formatting.AQUA, 46); + this.addSimpleIcoText(Ico.AMETHYST_SHARD, "Gemstone:", Formatting.DARK_PURPLE, 47); + } + +} diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java index 3f07622c..b0c5bf45 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Utils.java +++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java @@ -36,6 +36,9 @@ public class Utils { private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class); private static final String ALTERNATE_HYPIXEL_ADDRESS = System.getProperty("skyblocker.alternateHypixelAddress", ""); private static final String DUNGEONS_LOCATION = "dungeon"; + private static final String CRYSTAL_HOLLOWS_LOCATION = "crystal_hollows"; + private static final String DWARVEN_MINES_LOCATION = "mining_3"; + private static final String PROFILE_PREFIX = "Profile: "; private static boolean isOnHypixel = false; private static boolean isOnSkyblock = false; @@ -86,6 +89,14 @@ public class Utils { return getLocationRaw().equals(DUNGEONS_LOCATION) || FabricLoader.getInstance().isDevelopmentEnvironment(); } + public static boolean isInCrystalHollows() { + return getLocationRaw().equals(CRYSTAL_HOLLOWS_LOCATION) || FabricLoader.getInstance().isDevelopmentEnvironment(); + } + + public static boolean isInDwarvenMines() { + return getLocationRaw().equals(DWARVEN_MINES_LOCATION) || FabricLoader.getInstance().isDevelopmentEnvironment(); + } + public static boolean isInTheRift() { return getLocationRaw().equals(TheRift.LOCATION); } |