aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorJordan Bentkowski <109393182+617excelle@users.noreply.github.com>2025-07-31 06:28:38 +0200
committerGitHub <noreply@github.com>2025-07-31 00:28:38 -0400
commitfc49d9997e1702d977cb6f227c5771a0ca13c682 (patch)
tree7c89d2568a1b523e0cc16218a6a5a0df31bf6a99 /src/main/java
parent5b4decc2631c0acb8bbf5876d11ca8dfcb176acf (diff)
downloadSkyblocker-fc49d9997e1702d977cb6f227c5771a0ca13c682.tar.gz
Skyblocker-fc49d9997e1702d977cb6f227c5771a0ca13c682.tar.bz2
Skyblocker-fc49d9997e1702d977cb6f227c5771a0ca13c682.zip
Gyro wand radius overlay (#1317)
* Gyro wand radius overlay 4 Mode's and custom color selection! * review changes + local text file abc order * review changes + local text file abc order Fixes #1244 * change location of class in config file * empty line * pr cr's * naming fix * build errors fix * Language translation strings * fixed all bugs * javadoc merge removal fix * Spacing, Capitals wrong, indenting * Naming, Checkstyle fixes, javadoc fixes, naming fixes * Fix formatting --------- Co-authored-by: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java24
-rw-r--r--src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java355
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/GyroOverlay.java107
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java141
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderLayers.java9
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderPipelines.java10
6 files changed, 470 insertions, 176 deletions
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java
index 5da332e3..6c29ea6a 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java
@@ -4,6 +4,7 @@ import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.config.ConfigUtils;
import de.hysky.skyblocker.config.SkyblockerConfig;
import de.hysky.skyblocker.config.configs.UIAndVisualsConfig;
+import de.hysky.skyblocker.skyblock.GyroOverlay;
import de.hysky.skyblocker.skyblock.ItemPickupWidget;
import de.hysky.skyblocker.skyblock.TeleportOverlay;
import de.hysky.skyblocker.skyblock.fancybars.StatusBarsConfigScreen;
@@ -775,6 +776,29 @@ public class UIAndVisualsCategory {
.build())
.build()
)
+ //Gyro Overlay
+ .group(OptionGroup.createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.gyroOverlay"))
+ .collapsed(true)
+ .option(Option.<GyroOverlay.Mode>createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.gyroOverlay.modeSelect"))
+ .binding(defaults.uiAndVisuals.gyroOverlay.gyroOverlayMode,
+ () -> config.uiAndVisuals.gyroOverlay.gyroOverlayMode,
+ newValue -> config.uiAndVisuals.gyroOverlay.gyroOverlayMode = newValue)
+ .controller(ConfigUtils.createEnumController())
+ .build())
+ .option(Option.<Color>createBuilder()
+ .name(Text.translatable("skyblocker.config.uiAndVisuals.gyroOverlay.Color"))
+ .binding(defaults.uiAndVisuals.gyroOverlay.gyroOverlayColor,
+ () -> config.uiAndVisuals.gyroOverlay.gyroOverlayColor,
+ newValue -> {
+ config.uiAndVisuals.gyroOverlay.gyroOverlayColor = newValue;
+ GyroOverlay.configCallback(newValue);
+ })
+ .controller(ColourController.createBuilder().hasAlpha(true).build())
+ .build())
+ .build()
+ )
//item pickup widget
.group(OptionGroup.createBuilder()
diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java
index 9ad54784..4d535aa2 100644
--- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java
@@ -1,5 +1,6 @@
package de.hysky.skyblocker.config.configs;
+import de.hysky.skyblocker.skyblock.GyroOverlay;
import de.hysky.skyblocker.skyblock.item.slottext.SlotTextMode;
import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenBuilder;
import de.hysky.skyblocker.utils.waypoint.Waypoint;
@@ -17,73 +18,75 @@ public class UIAndVisualsConfig {
public int nightVisionStrength = 100;
- public boolean compactorDeletorPreview = true;
+ public boolean compactorDeletorPreview = true;
- public boolean dontStripSkinAlphaValues = true;
+ public boolean dontStripSkinAlphaValues = true;
- public boolean backpackPreviewWithoutShift = false;
+ public boolean backpackPreviewWithoutShift = false;
- public boolean hideEmptyTooltips = true;
+ public boolean hideEmptyTooltips = true;
- public boolean fancyCraftingTable = true;
+ public boolean fancyCraftingTable = true;
- public boolean hideStatusEffectOverlay = true;
+ public boolean hideStatusEffectOverlay = true;
- public boolean showEquipmentInInventory = true;
+ public boolean showEquipmentInInventory = true;
- public boolean cancelComponentUpdateAnimation = true;
+ public boolean cancelComponentUpdateAnimation = true;
public boolean showCustomizeButton = true;
public boolean showConfigButton = false;
- public ChestValue chestValue = new ChestValue();
+ public ChestValue chestValue = new ChestValue();
- public ItemCooldown itemCooldown = new ItemCooldown();
+ public ItemCooldown itemCooldown = new ItemCooldown();
public SlotText slotText = new SlotText();
- public InventorySearchConfig inventorySearch = new InventorySearchConfig();
+ public InventorySearchConfig inventorySearch = new InventorySearchConfig();
- public TitleContainer titleContainer = new TitleContainer();
+ public TitleContainer titleContainer = new TitleContainer();
- public TabHudConf tabHud = new TabHudConf();
+ public TabHudConf tabHud = new TabHudConf();
- public FancyAuctionHouse fancyAuctionHouse = new FancyAuctionHouse();
+ public FancyAuctionHouse fancyAuctionHouse = new FancyAuctionHouse();
- public Bars bars = new Bars();
+ public Bars bars = new Bars();
- public Waypoints waypoints = new Waypoints();
+ public Waypoints waypoints = new Waypoints();
- public TeleportOverlay teleportOverlay = new TeleportOverlay();
+ public TeleportOverlay teleportOverlay = new TeleportOverlay();
- public SmoothAOTE smoothAOTE = new SmoothAOTE();
+ public SmoothAOTE smoothAOTE = new SmoothAOTE();
- public SearchOverlay searchOverlay = new SearchOverlay();
+ public SearchOverlay searchOverlay = new SearchOverlay();
public BazaarQuickQuantities bazaarQuickQuantities = new BazaarQuickQuantities();
- public InputCalculator inputCalculator = new InputCalculator();
+ public InputCalculator inputCalculator = new InputCalculator();
- public FlameOverlay flameOverlay = new FlameOverlay();
+ public FlameOverlay flameOverlay = new FlameOverlay();
- public CompactDamage compactDamage = new CompactDamage();
+ public CompactDamage compactDamage = new CompactDamage();
public HealthBars healthBars = new HealthBars();
+ public GyrokineticWandOverlay gyroOverlay = new GyrokineticWandOverlay();
+
public ItemPickup itemPickup = new ItemPickup();
- public static class ChestValue {
- public boolean enableChestValue = true;
+ public static class ChestValue {
+ public boolean enableChestValue = true;
- public Formatting color = Formatting.DARK_GREEN;
+ public Formatting color = Formatting.DARK_GREEN;
- public Formatting incompleteColor = Formatting.BLUE;
- }
+ public Formatting incompleteColor = Formatting.BLUE;
+ }
- public static class ItemCooldown {
- public boolean enableItemCooldowns = true;
- }
+ public static class ItemCooldown {
+ public boolean enableItemCooldowns = true;
+ }
public static class SlotText {
public SlotTextMode slotTextMode = SlotTextMode.ENABLED;
@@ -94,88 +97,88 @@ public class UIAndVisualsConfig {
}
- public static class InventorySearchConfig {
- public EnableState enabled = EnableState.SKYBLOCK;
+ public static class InventorySearchConfig {
+ public EnableState enabled = EnableState.SKYBLOCK;
- public boolean ctrlK = false;
+ public boolean ctrlK = false;
- public boolean clickableText = false;
+ public boolean clickableText = false;
- public enum EnableState {
- OFF,
- SKYBLOCK,
- EVERYWHERE;
+ public enum EnableState {
+ OFF,
+ SKYBLOCK,
+ EVERYWHERE;
- @Override
- public String toString() {
- return I18n.translate("skyblocker.config.uiAndVisuals.inventorySearch.state." + this.name());
- }
+ @Override
+ public String toString() {
+ return I18n.translate("skyblocker.config.uiAndVisuals.inventorySearch.state." + this.name());
+ }
- public boolean isEnabled() {
- return switch (this) {
- case OFF -> false;
- case SKYBLOCK -> de.hysky.skyblocker.utils.Utils.isOnSkyblock();
- case EVERYWHERE -> true;
- };
- }
- }
- }
+ public boolean isEnabled() {
+ return switch (this) {
+ case OFF -> false;
+ case SKYBLOCK -> de.hysky.skyblocker.utils.Utils.isOnSkyblock();
+ case EVERYWHERE -> true;
+ };
+ }
+ }
+ }
- public static class TitleContainer {
- public float titleContainerScale = 100;
+ public static class TitleContainer {
+ public float titleContainerScale = 100;
- public int x = -1;
+ public int x = -1;
- public int y = -1;
+ public int y = -1;
- public Direction direction = Direction.VERTICAL;
+ public Direction direction = Direction.VERTICAL;
- public Alignment alignment = Alignment.MIDDLE;
+ public Alignment alignment = Alignment.MIDDLE;
- public float getRenderScale() {
- return titleContainerScale * 0.03f;
- }
- }
+ public float getRenderScale() {
+ return titleContainerScale * 0.03f;
+ }
+ }
- public enum Direction {
- HORIZONTAL, VERTICAL;
+ public enum Direction {
+ HORIZONTAL, VERTICAL;
- @Override
- public String toString() {
- return I18n.translate("skyblocker.config.uiAndVisuals.titleContainer.direction." + name());
- }
- }
+ @Override
+ public String toString() {
+ return I18n.translate("skyblocker.config.uiAndVisuals.titleContainer.direction." + name());
+ }
+ }
- public enum Alignment {
- LEFT, MIDDLE, RIGHT;
+ public enum Alignment {
+ LEFT, MIDDLE, RIGHT;
- @Override
- public String toString() {
- return I18n.translate("skyblocker.config.uiAndVisuals.titleContainer.alignment." + name());
- }
- }
+ @Override
+ public String toString() {
+ return I18n.translate("skyblocker.config.uiAndVisuals.titleContainer.alignment." + name());
+ }
+ }
- public static class TabHudConf {
- public boolean tabHudEnabled = true;
+ public static class TabHudConf {
+ public boolean tabHudEnabled = true;
- public int tabHudScale = 100;
+ public int tabHudScale = 100;
public boolean showVanillaTabByDefault = false;
public TabHudStyle style = TabHudStyle.FANCY;
- public boolean enableHudBackground = true;
+ public boolean enableHudBackground = true;
- public boolean effectsFromFooter = false;
+ public boolean effectsFromFooter = false;
- public ScreenBuilder.DefaultPositioner defaultPositioning = ScreenBuilder.DefaultPositioner.CENTERED;
+ public ScreenBuilder.DefaultPositioner defaultPositioning = ScreenBuilder.DefaultPositioner.CENTERED;
- @Deprecated
- public transient boolean plainPlayerNames = false;
+ @Deprecated
+ public transient boolean plainPlayerNames = false;
- @Deprecated
- public transient NameSorting nameSorting = NameSorting.DEFAULT;
- }
+ @Deprecated
+ public transient NameSorting nameSorting = NameSorting.DEFAULT;
+ }
public enum TabHudStyle {
/**
@@ -207,35 +210,35 @@ public class UIAndVisualsConfig {
}
}
- @Deprecated
- public enum NameSorting {
- DEFAULT, ALPHABETICAL;
+ @Deprecated
+ public enum NameSorting {
+ DEFAULT, ALPHABETICAL;
- @Override
- public String toString() {
- return switch (this) {
- case DEFAULT -> "Default";
- case ALPHABETICAL -> "Alphabetical";
- };
- }
- }
+ @Override
+ public String toString() {
+ return switch (this) {
+ case DEFAULT -> "Default";
+ case ALPHABETICAL -> "Alphabetical";
+ };
+ }
+ }
- public static class FancyAuctionHouse {
- public boolean enabled = false;
+ public static class FancyAuctionHouse {
+ public boolean enabled = false;
- public boolean highlightCheapBIN = true;
- }
+ public boolean highlightCheapBIN = true;
+ }
- public static class Bars {
- public boolean enableBars = true;
+ public static class Bars {
+ public boolean enableBars = true;
public IntelligenceDisplay intelligenceDisplay = IntelligenceDisplay.ORIGINAL;
- // Kept in for backwards compatibility, remove if needed
- @SuppressWarnings("DeprecatedIsStillUsed")
- @Deprecated
- public LegacyBarPositions barPositions = new LegacyBarPositions();
- }
+ // Kept in for backwards compatibility, remove if needed
+ @SuppressWarnings("DeprecatedIsStillUsed")
+ @Deprecated
+ public LegacyBarPositions barPositions = new LegacyBarPositions();
+ }
public enum IntelligenceDisplay {
ORIGINAL,
@@ -243,84 +246,84 @@ public class UIAndVisualsConfig {
IN_FRONT;
}
- /**
- * Backwards compat.
- * <p>
- * Used to load the legacy bar positions, which will not have an effect once the bars are saved in the new format at {@code /skyblocker/status_bars.json}.
- * New bars do not need to be added here.
- */
- @SuppressWarnings("DeprecatedIsStillUsed")
- @Deprecated
- public static class LegacyBarPositions {
- public LegacyBarPosition healthBarPosition = LegacyBarPosition.LAYER1;
+ /**
+ * Backwards compat.
+ * <p>
+ * Used to load the legacy bar positions, which will not have an effect once the bars are saved in the new format at {@code /skyblocker/status_bars.json}.
+ * New bars do not need to be added here.
+ */
+ @SuppressWarnings("DeprecatedIsStillUsed")
+ @Deprecated
+ public static class LegacyBarPositions {
+ public LegacyBarPosition healthBarPosition = LegacyBarPosition.LAYER1;
- public LegacyBarPosition manaBarPosition = LegacyBarPosition.LAYER1;
+ public LegacyBarPosition manaBarPosition = LegacyBarPosition.LAYER1;
- public LegacyBarPosition defenceBarPosition = LegacyBarPosition.RIGHT;
+ public LegacyBarPosition defenceBarPosition = LegacyBarPosition.RIGHT;
- public LegacyBarPosition experienceBarPosition = LegacyBarPosition.LAYER2;
- }
+ public LegacyBarPosition experienceBarPosition = LegacyBarPosition.LAYER2;
+ }
- /**
- * Backwards compat
- */
- public enum LegacyBarPosition {
- LAYER1, LAYER2, RIGHT, NONE
- }
+ /**
+ * Backwards compat
+ */
+ public enum LegacyBarPosition {
+ LAYER1, LAYER2, RIGHT, NONE
+ }
- public static class Waypoints {
- public boolean enableWaypoints = true;
+ public static class Waypoints {
+ public boolean enableWaypoints = true;
- public Waypoint.Type waypointType = Waypoint.Type.WAYPOINT;
- }
+ public Waypoint.Type waypointType = Waypoint.Type.WAYPOINT;
+ }
- public static class TeleportOverlay {
- public boolean enableTeleportOverlays = true;
+ public static class TeleportOverlay {
+ public boolean enableTeleportOverlays = true;
- public Color teleportOverlayColor = new Color(0x7F761594, true);
+ public Color teleportOverlayColor = new Color(0x7F761594, true);
- public boolean enableWeirdTransmission = false;
+ public boolean enableWeirdTransmission = false;
- public boolean enableInstantTransmission = false;
+ public boolean enableInstantTransmission = false;
- public boolean enableEtherTransmission = true;
+ public boolean enableEtherTransmission = true;
- public boolean enableSinrecallTransmission = false;
+ public boolean enableSinrecallTransmission = false;
- public boolean enableWitherImpact = false;
- }
+ public boolean enableWitherImpact = false;
+ }
- public static class SmoothAOTE {
- public boolean enableWeirdTransmission = false;
+ public static class SmoothAOTE {
+ public boolean enableWeirdTransmission = false;
- public boolean enableInstantTransmission = false;
+ public boolean enableInstantTransmission = false;
- public boolean enableEtherTransmission = false;
+ public boolean enableEtherTransmission = false;
- public boolean enableSinrecallTransmission = false;
+ public boolean enableSinrecallTransmission = false;
- public boolean enableWitherImpact = false;
+ public boolean enableWitherImpact = false;
public int maximumAddedLag = 100;
- }
+ }
- public static class SearchOverlay {
- public boolean enableBazaar = true;
+ public static class SearchOverlay {
+ public boolean enableBazaar = true;
- public boolean enableAuctionHouse = true;
+ public boolean enableAuctionHouse = true;
- public boolean keepPreviousSearches = false;
+ public boolean keepPreviousSearches = false;
- public int maxSuggestions = 3;
+ public int maxSuggestions = 3;
- public int historyLength = 3;
+ public int historyLength = 3;
- public boolean enableCommands = false;
+ public boolean enableCommands = false;
- public List<String> bazaarHistory = new ArrayList<>();
+ public List<String> bazaarHistory = new ArrayList<>();
- public List<String> auctionHistory = new ArrayList<>();
- }
+ public List<String> auctionHistory = new ArrayList<>();
+ }
public static class BazaarQuickQuantities {
public boolean enabled = false;
@@ -334,31 +337,31 @@ public class UIAndVisualsConfig {
public int slot3Quantity = 256;
}
- public static class InputCalculator {
- public boolean enabled = true;
+ public static class InputCalculator {
+ public boolean enabled = true;
- public boolean requiresEquals = false;
+ public boolean requiresEquals = false;
public boolean closeSignsWithEnter = true;
- }
+ }
- public static class FlameOverlay {
- public int flameHeight = 100;
+ public static class FlameOverlay {
+ public int flameHeight = 100;
- public int flameOpacity = 100;
- }
+ public int flameOpacity = 100;
+ }
- public static class CompactDamage {
- public boolean enabled = true;
+ public static class CompactDamage {
+ public boolean enabled = true;
- public int precision = 1;
+ public int precision = 1;
- public Color normalDamageColor = new Color(0xFFFFFF);
+ public Color normalDamageColor = new Color(0xFFFFFF);
- public Color critDamageGradientStart = new Color(0xFFFF55);
+ public Color critDamageGradientStart = new Color(0xFFFF55);
- public Color critDamageGradientEnd = new Color(0xFF5555);
- }
+ public Color critDamageGradientEnd = new Color(0xFF5555);
+ }
public static class HealthBars {
public boolean enabled = false;
@@ -380,6 +383,12 @@ public class UIAndVisualsConfig {
public Color emptyBarColor = new Color(0xFF0000);
}
+ public static class GyrokineticWandOverlay {
+ public GyroOverlay.Mode gyroOverlayMode = GyroOverlay.Mode.OFF;
+
+ public Color gyroOverlayColor = new Color(0x7F761594, true);
+ }
+
public static class ItemPickup {
public boolean enabled = false;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/GyroOverlay.java b/src/main/java/de/hysky/skyblocker/skyblock/GyroOverlay.java
new file mode 100644
index 00000000..6c6b71cf
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/GyroOverlay.java
@@ -0,0 +1,107 @@
+package de.hysky.skyblocker.skyblock;
+
+import de.hysky.skyblocker.annotations.Init;
+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.rendering.v1.WorldRenderContext;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.resource.language.I18n;
+import net.minecraft.util.StringIdentifiable;
+import net.minecraft.util.hit.HitResult;
+import net.minecraft.util.math.ColorHelper;
+import net.minecraft.util.math.Vec3d;
+
+import java.awt.*;
+
+
+public class GyroOverlay {
+ private static final MinecraftClient CLIENT = MinecraftClient.getInstance();
+
+ private static float[] colorComponents;
+
+ private static final int GYRO_RADIUS = 10;
+ private static final int SEGMENTS = 32;
+ private static final int MAX_REACH = 24;
+
+
+ // init ofcourse
+ @Init
+ public static void init() {
+ configCallback(SkyblockerConfigManager.get().uiAndVisuals.gyroOverlay.gyroOverlayColor);
+ WorldRenderEvents.AFTER_TRANSLUCENT.register(GyroOverlay::render);
+ }
+
+ // render
+ /**
+ * Renders a visual overlay in the world when the player is holding the Gyrokinetic Wand on Skyblock.
+ * <p>
+ * The overlay type depends on the configuration setting:
+ * <ul>
+ * <li>{@code OFF} – does not render anything.</li>
+ * <li>{@code CIRCLE_OUTLINE} – renders a ring-shaped outline using quads.</li>
+ * <li>{@code CIRCLE} – renders a filled circle.</li>
+ * <li>{@code SPHERE} – renders a 3D sphere.</li>
+ * </ul>
+ * The overlay is only rendered if:
+ * <ul>
+ * <li>The player is in a Skyblock world.</li>
+ * <li>The overlay mode is not {@code OFF}.</li>
+ * <li>The player is holding the {@code GYROKINETIC_WAND} in the main hand.</li>
+ * <li>The raycast from the camera hits a block or entity (i.e., not a miss).</li>
+ * </ul>
+ *
+ * @param wrc The {@link WorldRenderContext} provided during world rendering,
+ * containing rendering matrices and utilities for rendering custom elements.
+ */
+ public static void render(WorldRenderContext wrc) {
+ if (CLIENT.player == null || CLIENT.world == null) return;
+ if (!Utils.isOnSkyblock()) return;
+ if (SkyblockerConfigManager.get().uiAndVisuals.gyroOverlay.gyroOverlayMode == Mode.OFF) return;
+
+ String heldItem = CLIENT.player.getMainHandStack().getSkyblockId();
+ if (!heldItem.equals("GYROKINETIC_WAND")) return;
+
+ HitResult hit = CLIENT.cameraEntity.raycast(MAX_REACH, 1.0f, false);
+ if (hit.getType() == HitResult.Type.MISS) {
+ return;
+ }
+
+ int color = ColorHelper.fromFloats(colorComponents[3], colorComponents[0], colorComponents[1], colorComponents[2]);
+
+ switch (SkyblockerConfigManager.get().uiAndVisuals.gyroOverlay.gyroOverlayMode) {
+ case OFF -> {}
+ case CIRCLE_OUTLINE -> RenderHelper.renderCircleOutlineWithQuads(wrc, hit.getPos().add(new Vec3d(0, 0.1, 0)), GYRO_RADIUS, 0.25f, SEGMENTS, color);
+ case CIRCLE -> RenderHelper.renderCircleFilled(wrc, hit.getPos().add(new Vec3d(0, 0.1, 0)), GYRO_RADIUS, SEGMENTS, color);
+ case SPHERE -> RenderHelper.renderSphere(wrc, hit.getPos(), GYRO_RADIUS, SEGMENTS, SEGMENTS, color);
+ }
+ }
+
+ public static void configCallback(Color color) {
+ colorComponents = color.getRGBComponents(null);
+ }
+
+ public enum Mode implements StringIdentifiable {
+ OFF("OFF"),
+ CIRCLE("CIRCLE"),
+ CIRCLE_OUTLINE("CIRCLE_OUTLINE"),
+ SPHERE("SPHERE");
+
+ private final String key;
+
+ Mode(String key) {
+ this.key = "skyblocker.config.uiAndVisuals.gyroOverlay.mode." + key;
+ }
+
+ @Override
+ public String asString() {
+ return name().toLowerCase();
+ }
+
+ @Override
+ public String toString() {
+ return I18n.translate(this.key);
+ }
+ }
+}
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 7ca2049a..8789d644 100644
--- a/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java
+++ b/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java
@@ -310,9 +310,10 @@ public class RenderHelper {
/**
* Renders a cylinder without the top or bottom faces.
*
- * @param pos The position that the cylinder will be centred around.
+ * @param centre The position that the circle will be centred around.
+ * @param radius The radius of the cylinder.
* @param height The total height of the cylinder with {@code pos} as the midpoint.
- * @param segments The amount of triangles used to approximate the circle.
+ * @param segments The number of triangles used to approximate the circle.
*/
public static void renderCylinder(WorldRenderContext context, Vec3d centre, float radius, float height, int segments, int color) {
MatrixStack matrices = context.matrixStack();
@@ -337,7 +338,141 @@ public class RenderHelper {
matrices.pop();
}
- /**
+ /**
+ * Renders a circle filled in using triangle_fan drawmode
+ *
+ * @param centre The position that the circle will be centred around.
+ * @param radius The radius of the circle.
+ * @param segments The number of triangles used to approximate the circle.
+ * @param color The color of the circle as an argb int.
+ */
+ public static void renderCircleFilled(WorldRenderContext context, Vec3d centre, float radius, int segments, int color) {
+ MatrixStack matrices = context.matrixStack();
+ Vec3d camera = context.camera().getPos();
+
+ matrices.push();
+ matrices.translate(-camera.x, -camera.y, -camera.z);
+ VertexConsumer buffer = context.consumers().getBuffer(SkyblockerRenderLayers.CIRCLE);
+ Matrix4f positionMatrix = matrices.peek().getPositionMatrix();
+
+ for (int i = 0; i <= segments; i++) {
+ double angle = Math.TAU * i / segments;
+ float dx = (float) Math.cos(angle) * radius;
+ float dz = (float) Math.sin(angle) * radius;
+
+ buffer.vertex(positionMatrix, (float) centre.getX() + dx, (float) centre.getY(), (float) centre.getZ() + dz).color(color);
+ }
+
+ matrices.pop();
+ }
+
+ /**
+ * Renders a circle sphere in using triange_strip
+ *
+ * @param centre The position that the circle will be centred around.
+ * @param radius The radius of the sphere.
+ * @param rings The number of rings to subdivide the sphere.
+ * @param segments The number of triangles used to approximate the circle.
+ * @param color The color of the circle as an argb int.
+ */
+ public static void renderSphere(WorldRenderContext context, Vec3d centre, float radius, int segments, int rings, int color) {
+ MatrixStack matrices = context.matrixStack();
+ Vec3d camera = context.camera().getPos();
+
+ matrices.push();
+ matrices.translate(-camera.x, -camera.y, -camera.z);
+
+ VertexConsumer buffer = context.consumers().getBuffer(SkyblockerRenderLayers.CYLINDER);
+ Matrix4f positionMatrix = matrices.peek().getPositionMatrix();
+
+ for (int lat = 0; lat < rings; lat++) {
+ double lat0 = Math.PI * (double) lat / rings;
+ double lat1 = Math.PI * (double) (lat + 1) / rings;
+
+ float y0 = (float) Math.cos(lat0) * radius;
+ float y1 = (float) Math.cos(lat1) * radius;
+
+ float r0 = (float) Math.sin(lat0) * radius;
+ float r1 = (float) Math.sin(lat1) * radius;
+
+ for (int lon = 0; lon <= segments; lon++) {
+ double angle = Math.TAU * (double) lon / segments;
+ float x0 = (float) Math.cos(angle);
+ float z0 = (float) Math.sin(angle);
+
+ // First triangle
+ buffer.vertex(positionMatrix,
+ Math.fma(x0, r0, (float) centre.getX()),
+ (float) centre.getY() + y0,
+ Math.fma(z0, r0, (float) centre.getZ()))
+ .color(color);
+
+ buffer.vertex(positionMatrix,
+ Math.fma(x0, r1, (float) centre.getX()),
+ (float) centre.getY() + y1,
+ Math.fma(z0, r1, (float) centre.getZ()))
+ .color(color);
+ }
+ }
+
+ matrices.pop();
+ }
+
+ /**
+ * Renders a circle outline in using quads
+ *
+ * @param centre The position that the circle will be centred around.
+ * @param radius The radius of the circle.
+ * @param thickness The thickness of the outline in blocks.
+ * @param segments The number of triangles used to approximate the circle.
+ * @param color The color of the circle as an argb int.
+ */
+ public static void renderCircleOutlineWithQuads(WorldRenderContext context, Vec3d centre, float radius, float thickness, int segments, int color) {
+ MatrixStack matrices = context.matrixStack();
+ Vec3d camera = context.camera().getPos();
+
+ matrices.push();
+ matrices.translate(-camera.x, -camera.y, -camera.z);
+
+ VertexConsumer buffer = context.consumers().getBuffer(SkyblockerRenderLayers.CIRCLE_LINES);
+ Matrix4f positionMatrix = matrices.peek().getPositionMatrix();
+
+
+ float innerRadius = radius - thickness / 2f;
+ float outerRadius = radius + thickness / 2f;
+
+ for (int i = 0; i < segments; i++) {
+ double angle1 = Math.TAU * i / segments;
+ double angle2 = Math.TAU * (i + 1) / segments;
+
+ float x1Inner = (float) Math.cos(angle1) * innerRadius;
+ float z1Inner = (float) Math.sin(angle1) * innerRadius;
+
+ float x1Outer = (float) Math.cos(angle1) * outerRadius;
+ float z1Outer = (float) Math.sin(angle1) * outerRadius;
+
+ float x2Inner = (float) Math.cos(angle2) * innerRadius;
+ float z2Inner = (float) Math.sin(angle2) * innerRadius;
+
+ float x2Outer = (float) Math.cos(angle2) * outerRadius;
+ float z2Outer = (float) Math.sin(angle2) * outerRadius;
+
+ float cx = (float) centre.getX();
+ float cy = (float) centre.getY();
+ float cz = (float) centre.getZ();
+
+ // Each quad is formed from two triangles
+ buffer.vertex(positionMatrix, cx + x1Inner, cy, cz + z1Inner).color(color);
+ buffer.vertex(positionMatrix, cx + x1Outer, cy, cz + z1Outer).color(color);
+ buffer.vertex(positionMatrix, cx + x2Outer, cy, cz + z2Outer).color(color);
+ buffer.vertex(positionMatrix, cx + x2Inner, cy, cz + z2Inner).color(color);
+ }
+
+ matrices.pop();
+ }
+
+
+ /**
* This is called after all {@link WorldRenderEvents#AFTER_TRANSLUCENT} listeners have been called so that we can draw all remaining render layers.
*/
private static void drawTranslucents(WorldRenderContext context) {
diff --git a/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderLayers.java b/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderLayers.java
index a87d9cbc..865521ed 100644
--- a/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderLayers.java
+++ b/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderLayers.java
@@ -58,10 +58,19 @@ public class SkyblockerRenderLayers {
.texture(new RenderPhase.Texture(texture, TriState.FALSE, false))
.layering(RenderPhase.VIEW_OFFSET_Z_LAYERING)
.build(false));
+
public static final MultiPhase CYLINDER = RenderLayer.of("cylinder", RenderLayer.DEFAULT_BUFFER_SIZE, false, true, SkyblockerRenderPipelines.CYLINDER, MultiPhaseParameters.builder()
.layering(RenderPhase.VIEW_OFFSET_Z_LAYERING)
.build(false));
+ public static final MultiPhase CIRCLE = RenderLayer.of("circle", RenderLayer.DEFAULT_BUFFER_SIZE, false, true, SkyblockerRenderPipelines.CIRCLE, MultiPhaseParameters.builder()
+ .layering(RenderPhase.VIEW_OFFSET_Z_LAYERING)
+ .build(false));
+
+ public static final MultiPhase CIRCLE_LINES = RenderLayer.of("circle_lines", RenderLayer.DEFAULT_BUFFER_SIZE, false, true, SkyblockerRenderPipelines.CIRCLE_LINES, MultiPhaseParameters.builder()
+ .layering(RenderPhase.VIEW_OFFSET_Z_LAYERING)
+ .build(false));
+
public static MultiPhase getLines(double lineWidth) {
return LINES_LAYERS.computeIfAbsent(lineWidth, LINES);
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderPipelines.java b/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderPipelines.java
index cbd73e1c..dd4374b5 100644
--- a/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderPipelines.java
+++ b/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderPipelines.java
@@ -43,6 +43,16 @@ public class SkyblockerRenderPipelines {
.withVertexFormat(VertexFormats.POSITION_COLOR, DrawMode.TRIANGLE_STRIP)
.withCull(false)
.build());
+ static final RenderPipeline CIRCLE = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.POSITION_COLOR_SNIPPET)
+ .withLocation(Identifier.of(SkyblockerMod.NAMESPACE, "pipeline/circle"))
+ .withVertexFormat(VertexFormats.POSITION_COLOR, DrawMode.TRIANGLE_FAN)
+ .withCull(false)
+ .build());
+ static final RenderPipeline CIRCLE_LINES = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.POSITION_COLOR_SNIPPET)
+ .withLocation(Identifier.of(SkyblockerMod.NAMESPACE, "pipeline/circle_lines"))
+ .withVertexFormat(VertexFormats.POSITION_COLOR, DrawMode.QUADS)
+ .withCull(false)
+ .build());
@Init
public static void init() {} //Ensure that pipelines are pre-compiled instead of compiled on demand