diff options
| author | Jordan Bentkowski <109393182+617excelle@users.noreply.github.com> | 2025-07-31 06:28:38 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-31 00:28:38 -0400 |
| commit | fc49d9997e1702d977cb6f227c5771a0ca13c682 (patch) | |
| tree | 7c89d2568a1b523e0cc16218a6a5a0df31bf6a99 /src/main/java | |
| parent | 5b4decc2631c0acb8bbf5876d11ca8dfcb176acf (diff) | |
| download | Skyblocker-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')
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 |
