From a45227810a73c7b4e79960f4d775d6c91389f43d Mon Sep 17 00:00:00 2001 From: olim Date: Thu, 11 Jul 2024 13:17:28 +0100 Subject: create feature --- .../java/de/hysky/skyblocker/SkyblockerMod.java | 1 + .../config/categories/MiningCategory.java | 27 +++++-- .../skyblocker/config/configs/MiningConfig.java | 8 ++ .../hysky/skyblocker/mixins/ClientWorldMixin.java | 6 +- .../skyblock/dwarven/CrystalsChestHighlighter.java | 88 ++++++++++++++++++++++ .../skyblocker/utils/render/RenderHelper.java | 36 +++++++++ 6 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsChestHighlighter.java (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index b1d25a01..d5b8204f 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -134,6 +134,7 @@ public class SkyblockerMod implements ClientModInitializer { LowerSensitivity.init(); CrystalsLocationsManager.init(); WishingCompassSolver.init(); + CrystalsChestHighlighter.init(); MetalDetector.init(); ChatMessageListener.init(); Shortcuts.init(); diff --git a/src/main/java/de/hysky/skyblocker/config/categories/MiningCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/MiningCategory.java index 796a6105..74be78cb 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/MiningCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/MiningCategory.java @@ -4,17 +4,16 @@ import de.hysky.skyblocker.config.ConfigUtils; import de.hysky.skyblocker.config.SkyblockerConfig; import de.hysky.skyblocker.config.configs.MiningConfig; 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.*; +import dev.isxander.yacl3.api.controller.ColorControllerBuilder; import dev.isxander.yacl3.api.controller.FloatFieldControllerBuilder; import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; import net.minecraft.client.MinecraftClient; import net.minecraft.text.Text; +import java.awt.*; + public class MiningCategory { public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig config) { @@ -111,7 +110,23 @@ public class MiningCategory { newValue -> config.mining.crystalHollows.nucleusWaypoints = newValue) .controller(ConfigUtils::createBooleanController) .build()) - .build()) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.mining.crystalHollows.chestHighlighter")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.mining.crystalHollows.chestHighlighter.@Tooltip"))) + .binding(defaults.mining.crystalHollows.chestHighlighter, + () -> config.mining.crystalHollows.chestHighlighter, + newValue -> config.mining.crystalHollows.chestHighlighter = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.mining.crystalHollows.chestHighlighter.color")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.mining.crystalHollows.chestHighlighter.color.@Tooltip"))) + .binding(defaults.mining.crystalHollows.chestHighlightColor, + () -> config.mining.crystalHollows.chestHighlightColor, + newValue -> config.mining.crystalHollows.chestHighlightColor = newValue) + .controller(v -> ColorControllerBuilder.create(v).allowAlpha(true)) + .build()) + .build()) //Crystal Hollows Map .group(OptionGroup.createBuilder() diff --git a/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java index dcf70f24..5236f1eb 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/MiningConfig.java @@ -2,6 +2,8 @@ package de.hysky.skyblocker.config.configs; import dev.isxander.yacl3.config.v2.api.SerialEntry; +import java.awt.*; + public class MiningConfig { @SerialEntry public boolean enableDrillFuel = true; @@ -67,6 +69,12 @@ public class MiningConfig { @SerialEntry public boolean nucleusWaypoints = false; + + @SerialEntry + public boolean chestHighlighter = true; + + @SerialEntry + public Color chestHighlightColor = new Color(0, 0, 255, 128); } public static class CrystalsHud { diff --git a/src/main/java/de/hysky/skyblocker/mixins/ClientWorldMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ClientWorldMixin.java index a2d7887b..fdc199e8 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ClientWorldMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ClientWorldMixin.java @@ -2,6 +2,7 @@ package de.hysky.skyblocker.mixins; import de.hysky.skyblocker.skyblock.crimson.dojo.DojoManager; import de.hysky.skyblocker.skyblock.dungeon.device.SimonSays; +import de.hysky.skyblocker.skyblock.dwarven.CrystalsChestHighlighter; import de.hysky.skyblocker.utils.Utils; import net.minecraft.block.BlockState; import net.minecraft.client.world.ClientWorld; @@ -25,7 +26,10 @@ public class ClientWorldMixin { if (Utils.isInCrimson()) { DojoManager.onBlockUpdate(pos.toImmutable(), state); } - + else if (Utils.isInCrystalHollows()) { + CrystalsChestHighlighter.onBlockUpdate(pos.toImmutable(), state); + } SimonSays.onBlockUpdate(pos, state); + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsChestHighlighter.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsChestHighlighter.java new file mode 100644 index 00000000..ded2e678 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsChestHighlighter.java @@ -0,0 +1,88 @@ +package de.hysky.skyblocker.skyblock.dwarven; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.render.RenderHelper; +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.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.Text; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; + +import java.util.ArrayList; +import java.util.List; + +public class CrystalsChestHighlighter { + + private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); + private static final String CHEST_SPAWN_MESSAGE = "You uncovered a treasure chest!"; + + private static int waitingForChest = 0; + private static final List activeChests = new ArrayList<>(); + + public static void init() { + ClientReceiveMessageEvents.GAME.register(CrystalsChestHighlighter::extractLocationFromMessage); + WorldRenderEvents.AFTER_TRANSLUCENT.register(CrystalsChestHighlighter::render); + ClientPlayConnectionEvents.JOIN.register((_handler, _sender, _client) -> reset()); + } + + private static void reset() { + waitingForChest = 0; + activeChests.clear(); + } + + private static void extractLocationFromMessage(Text text, boolean b) { + if (!Utils.isInCrystalHollows() || !SkyblockerConfigManager.get().mining.crystalHollows.chestHighlighter) { + return; + } + //if a chest is spawned add chest to look for + if (text.getString().matches(CHEST_SPAWN_MESSAGE)) { + waitingForChest += 1; + } + } + + /** + * When a block is updated in the crystal hollows if looking for a chest see if it's a chest and if so add to active. or remove active chests from where air is placed + * + * @param pos location of block update + * @param state the new state of the block + */ + public static void onBlockUpdate(BlockPos pos, BlockState state) { + if (!SkyblockerConfigManager.get().mining.crystalHollows.chestHighlighter || CLIENT.player == null) { + return; + } + if (waitingForChest > 0 && state.isOf(Blocks.CHEST)) { + //make sure it is not too far from the player (more than 10 blocks away) + if (pos.getSquaredDistance(CLIENT.player.getPos()) > 100) { + return; + } + activeChests.add(pos); + waitingForChest -= 1; + } else if (state.isAir()) { + activeChests.remove(pos); + } + + + } + + /** + * Renders a box around active treasure chests if enabled. Taking the color from the config + * + * @param context context + */ + private static void render(WorldRenderContext context) { + if (!Utils.isInCrystalHollows() || !SkyblockerConfigManager.get().mining.crystalHollows.chestHighlighter) { + return; + } + float[] color = SkyblockerConfigManager.get().mining.crystalHollows.chestHighlightColor.getComponents(new float[]{0, 0, 0, 0}); + for (BlockPos chest : activeChests) { + RenderHelper.renderOutline(context, Box.of(chest.toCenterPos().subtract(0, 0.0625, 0), 0.875, 0.875, 0.875), color, color[3], 3, true); + } + + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java b/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java index 20d8157a..1106dee8 100644 --- a/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java +++ b/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java @@ -146,6 +146,42 @@ public class RenderHelper { } } + /** + * Renders the outline of a box with the specified color components and line width. + * This does not use renderer since renderer draws outline using debug lines with a fixed width. + * + * @param alpha the transparency of the lines for the box + */ + public static void renderOutline(WorldRenderContext context, Box box, float[] colorComponents, float alpha, float lineWidth, boolean throughWalls) { + if (FrustumUtils.isVisible(box)) { + MatrixStack matrices = context.matrixStack(); + Vec3d camera = context.camera().getPos(); + Tessellator tessellator = RenderSystem.renderThreadTesselator(); + + RenderSystem.setShader(GameRenderer::getRenderTypeLinesProgram); + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + RenderSystem.enableBlend(); + RenderSystem.lineWidth(lineWidth); + RenderSystem.disableCull(); + RenderSystem.enableDepthTest(); + RenderSystem.depthFunc(throughWalls ? GL11.GL_ALWAYS : GL11.GL_LEQUAL); + + matrices.push(); + matrices.translate(-camera.getX(), -camera.getY(), -camera.getZ()); + + BufferBuilder buffer = tessellator.begin(DrawMode.LINES, VertexFormats.LINES); + WorldRenderer.drawBox(matrices, buffer, box, colorComponents[0], colorComponents[1], colorComponents[2], alpha); + BufferRenderer.drawWithGlobalProgram(buffer.end()); + + matrices.pop(); + RenderSystem.lineWidth(1f); + RenderSystem.enableCull(); + RenderSystem.disableBlend(); + RenderSystem.disableDepthTest(); + RenderSystem.depthFunc(GL11.GL_LEQUAL); + } + } + /** * Draws lines from point to point.

*

-- cgit