From d32f1249743ec451688dae815bb1d2c5ffac4846 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 22 Feb 2026 04:27:30 +0100 Subject: [PATCH 01/18] Removed todos --- .../java/org/saturnclient/saturnclient/cosmetics/Hats.java | 5 +---- .../saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java index 0d2b7cf..ced3e77 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java @@ -24,10 +24,7 @@ public class Hats { public static void setHat(UUID uuid, String hatName) { SaturnPlayer player = SaturnPlayer.get(uuid); - if (player == null) { - // Auth.players.put(uuid, new SaturnPlayer("", hatName)); - // TODO: address this behaviour - } else { + if (player != null) { player.hat = hatName; } } diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java index 32e3283..d624942 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java @@ -76,10 +76,7 @@ public class Cloaks { public static void setCloak(UUID uuid, String cloakName) { SaturnPlayer player = SaturnPlayer.get(uuid); - if (player == null) { - // Auth.players.put(uuid, new SaturnPlayer(cloakName, null)); - // TODO: Address this functionality - } else { + if (player != null) { player.cloak = cloakName; } From 7fc05df240a00a214bb303d095b967e7cd1a5988 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 22 Feb 2026 14:35:57 +0100 Subject: [PATCH 02/18] Svg image rendering --- build.gradle | 3 + .../ui2/resources/SvgTexture.java | 65 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/main/java/org/saturnclient/ui2/resources/SvgTexture.java diff --git a/build.gradle b/build.gradle index 3fcc938..208e588 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,9 @@ dependencies { implementation 'com.github.selimaj-dev:session-java:0.1.4' + modImplementation "org.apache.xmlgraphics:batik-transcoder:1.19" + modImplementation "org.apache.xmlgraphics:batik-codec:1.19" + include modImplementation("dev.kosmx.player-anim:player-animation-lib-fabric:${project.player_anim}") //You might want bendy-lib. playerAnimator will wrap it. // include modRuntimeOnly("io.github.kosmx.bendy-lib:bendy-lib-fabric:${project.bendylib_version}") diff --git a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java new file mode 100644 index 0000000..f1baacc --- /dev/null +++ b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java @@ -0,0 +1,65 @@ +package org.saturnclient.ui2.resources; + +import java.awt.image.BufferedImage; +import java.io.InputStream; + +import org.apache.batik.transcoder.TranscoderInput; +import org.apache.batik.transcoder.image.ImageTranscoder; +import org.jetbrains.annotations.Nullable; +import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.Identifier; + +public class SvgTexture { + private static BufferedImage renderSvg(InputStream svgStream, float width, float height) throws Exception { + TranscoderInput input = new TranscoderInput(svgStream); + + final BufferedImage[] imagePointer = new BufferedImage[1]; + + ImageTranscoder transcoder = new ImageTranscoder() { + + @Override + public BufferedImage createImage(int w, int h) { + return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + } + + @Override + public void writeImage(BufferedImage img, org.apache.batik.transcoder.TranscoderOutput out) { + imagePointer[0] = img; + } + }; + + transcoder.addTranscodingHint(ImageTranscoder.KEY_WIDTH, width); + transcoder.addTranscodingHint(ImageTranscoder.KEY_HEIGHT, height); + + transcoder.transcode(input, null); + + return imagePointer[0]; + } + + @Nullable + @SuppressWarnings("resource") + public static Identifier getSvg(MinecraftClient client, Identifier svgImage, int width, int height, float scale) { + try (InputStream svgStream = client + .getResourceManager() + .getResource(svgImage).get() + .getInputStream()) { + + BufferedImage image = renderSvg(svgStream, width, height); + + System.out.println(svgImage.toString()); + + Identifier id = Identifier.of(SaturnClient.MOD_ID, "img_svg_render_" + (int) (Math.random() * 30)); + IdentifierUtils.registerBufferedImageTexture(id, image); + + return id; + + } catch (Exception e) { + e.printStackTrace(); + + return null; + } + } +} From 66b96102f8e0e7f1749c896e675020093a18fbee Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 22 Feb 2026 16:41:26 +0100 Subject: [PATCH 03/18] Working svg renderer --- build.gradle | 8 ++-- .../ui2/resources/SvgTexture.java | 44 +++++++++---------- .../saturnclient/ui2/screens/TitleMenu.java | 6 +++ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/build.gradle b/build.gradle index 208e588..1266b7f 100644 --- a/build.gradle +++ b/build.gradle @@ -22,8 +22,8 @@ dependencies { implementation 'com.github.selimaj-dev:session-java:0.1.4' - modImplementation "org.apache.xmlgraphics:batik-transcoder:1.19" - modImplementation "org.apache.xmlgraphics:batik-codec:1.19" + // implementation("com.kitfox.svg:svg-salamander:1.1.3") + implementation 'com.formdev:svgSalamander:1.1.4' include modImplementation("dev.kosmx.player-anim:player-animation-lib-fabric:${project.player_anim}") //You might want bendy-lib. playerAnimator will wrap it. @@ -32,11 +32,13 @@ dependencies { repositories { - maven { url 'https://maven.fabricmc.net/' } // Fabric's official repo + maven { url 'https://maven.fabricmc.net/' } maven { url 'https://jitpack.io' } maven { url "https://maven.parchmentmc.org" } maven { name = "FelNull Maven"; url = "https://maven.felnull.dev" } maven { name = "KosmX maven"; url = 'https://maven.kosmx.dev/' } + + mavenCentral() } processResources { diff --git a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java index f1baacc..c7a6482 100644 --- a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java +++ b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java @@ -1,10 +1,13 @@ package org.saturnclient.ui2.resources; +import java.awt.Graphics2D; +import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.InputStream; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.batik.transcoder.image.ImageTranscoder; +import com.kitfox.svg.SVGDiagram; +import com.kitfox.svg.SVGUniverse; + import org.jetbrains.annotations.Nullable; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; @@ -13,30 +16,26 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.util.Identifier; public class SvgTexture { - private static BufferedImage renderSvg(InputStream svgStream, float width, float height) throws Exception { - TranscoderInput input = new TranscoderInput(svgStream); - final BufferedImage[] imagePointer = new BufferedImage[1]; + private static BufferedImage renderSvg(InputStream svgStream, int width, int height) throws Exception { + // Create SVGUniverse and load the SVG + SVGUniverse universe = new SVGUniverse(); + java.net.URI uri = universe.loadSVG(svgStream, "tempSvg"); + SVGDiagram diagram = universe.getDiagram(uri); - ImageTranscoder transcoder = new ImageTranscoder() { + // Create a BufferedImage to render the SVG + BufferedImage image = new BufferedImage((int) width, (int) height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); - @Override - public BufferedImage createImage(int w, int h) { - return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - } + // Set the diagram's viewport to match the desired size + diagram.setIgnoringClipHeuristic(true); + diagram.setDeviceViewport(new Rectangle(0, 0, width, height)); - @Override - public void writeImage(BufferedImage img, org.apache.batik.transcoder.TranscoderOutput out) { - imagePointer[0] = img; - } - }; + // Render the SVG onto the BufferedImage + diagram.render(g); - transcoder.addTranscodingHint(ImageTranscoder.KEY_WIDTH, width); - transcoder.addTranscodingHint(ImageTranscoder.KEY_HEIGHT, height); - - transcoder.transcode(input, null); - - return imagePointer[0]; + g.dispose(); + return image; } @Nullable @@ -58,8 +57,7 @@ public class SvgTexture { } catch (Exception e) { e.printStackTrace(); - return null; } } -} +} \ No newline at end of file diff --git a/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java b/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java index ebffa12..a132199 100644 --- a/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java @@ -14,10 +14,12 @@ import org.saturnclient.ui2.elements.Button; import org.saturnclient.ui2.elements.ImageTexture; import org.saturnclient.ui2.elements.TextureButton; import org.saturnclient.ui2.resources.Fonts; +import org.saturnclient.ui2.resources.SvgTexture; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; +import net.minecraft.util.Identifier; public class TitleMenu extends SaturnScreen { public TitleMenu() { @@ -70,5 +72,9 @@ public class TitleMenu extends SaturnScreen { }).dimensions(s, s).position((s + 2) * 2, 0).animation(new SlideFade(1000, s + 8))); draw(saturnStagger.dimensions(((s + 2) * 2) + s, s).centerHorizontal(width, height, 0, 8)); + + draw(new ImageTexture( + SvgTexture.getSvg(client, Identifier.of("saturnclient", "textures/gui/test.svg"), 98, 98, 1.0f)) + .dimensions(98, 98)); } } From 3c27d3b377bc1ce5e0e5f4e86bc3ec261c1ff13d Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 22 Feb 2026 16:41:37 +0100 Subject: [PATCH 04/18] Working svg renderer --- src/main/resources/assets/saturnclient/textures/gui/test.svg | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/main/resources/assets/saturnclient/textures/gui/test.svg diff --git a/src/main/resources/assets/saturnclient/textures/gui/test.svg b/src/main/resources/assets/saturnclient/textures/gui/test.svg new file mode 100644 index 0000000..15e0aff --- /dev/null +++ b/src/main/resources/assets/saturnclient/textures/gui/test.svg @@ -0,0 +1 @@ + \ No newline at end of file From 9caf47d81b112fc3ac22278559ef1c696d42cb09 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 22 Feb 2026 18:11:58 +0100 Subject: [PATCH 05/18] Fixed svg issues --- .../ui2/elements/ImageTexture.java | 14 +++++++-- .../ui2/resources/SvgTexture.java | 29 +++++++++++++------ .../saturnclient/ui2/screens/TitleMenu.java | 6 ---- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/saturnclient/ui2/elements/ImageTexture.java b/src/main/java/org/saturnclient/ui2/elements/ImageTexture.java index b5d9426..037ef31 100644 --- a/src/main/java/org/saturnclient/ui2/elements/ImageTexture.java +++ b/src/main/java/org/saturnclient/ui2/elements/ImageTexture.java @@ -3,8 +3,9 @@ package org.saturnclient.ui2.elements; import org.saturnclient.ui2.Element; import org.saturnclient.ui2.ElementContext; import org.saturnclient.ui2.RenderScope; +import org.saturnclient.ui2.resources.SvgTexture; -import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.MinecraftClient; import net.minecraft.util.Identifier; public class ImageTexture extends Element { @@ -16,7 +17,16 @@ public class ImageTexture extends Element { @Override public void render(RenderScope renderScope, ElementContext ctx) { - renderScope.setRenderLayer(RenderLayer::getGuiTextured); + if (sprite.toString().endsWith(".svg")) { + MinecraftClient client = MinecraftClient.getInstance(); + + // Get the actual window pixel dimensions for the image + int renderWidth = (int) (width * client.getWindow().getFramebufferWidth() / client.getWindow().getWidth()); + int renderHeight = (int) (height * client.getWindow().getFramebufferHeight() / client.getWindow().getHeight()); + + sprite = SvgTexture.getSvg(client, sprite, renderWidth * 2, renderHeight * 2); + } + renderScope.drawTexture(sprite, 0, 0, 0, 0, width, height); } } diff --git a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java index c7a6482..438a190 100644 --- a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java +++ b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java @@ -1,7 +1,7 @@ package org.saturnclient.ui2.resources; import java.awt.Graphics2D; -import java.awt.Rectangle; +import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.InputStream; @@ -18,20 +18,31 @@ import net.minecraft.util.Identifier; public class SvgTexture { private static BufferedImage renderSvg(InputStream svgStream, int width, int height) throws Exception { - // Create SVGUniverse and load the SVG + // Load SVG SVGUniverse universe = new SVGUniverse(); java.net.URI uri = universe.loadSVG(svgStream, "tempSvg"); SVGDiagram diagram = universe.getDiagram(uri); - // Create a BufferedImage to render the SVG - BufferedImage image = new BufferedImage((int) width, (int) height, BufferedImage.TYPE_INT_ARGB); + // Get intrinsic size of SVG + float svgWidth = (float) diagram.getWidth(); + float svgHeight = (float) diagram.getHeight(); + + // Compute scale factors + float scaleX = width / svgWidth; + float scaleY = height / svgHeight; + + // Create output image + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = image.createGraphics(); - // Set the diagram's viewport to match the desired size - diagram.setIgnoringClipHeuristic(true); - diagram.setDeviceViewport(new Rectangle(0, 0, width, height)); + // Enable anti-aliasing for smooth scaling + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - // Render the SVG onto the BufferedImage + // Apply scaling transform + g.scale(scaleX, scaleY); + + // Render SVG diagram.render(g); g.dispose(); @@ -40,7 +51,7 @@ public class SvgTexture { @Nullable @SuppressWarnings("resource") - public static Identifier getSvg(MinecraftClient client, Identifier svgImage, int width, int height, float scale) { + public static Identifier getSvg(MinecraftClient client, Identifier svgImage, int width, int height) { try (InputStream svgStream = client .getResourceManager() .getResource(svgImage).get() diff --git a/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java b/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java index a132199..ebffa12 100644 --- a/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java @@ -14,12 +14,10 @@ import org.saturnclient.ui2.elements.Button; import org.saturnclient.ui2.elements.ImageTexture; import org.saturnclient.ui2.elements.TextureButton; import org.saturnclient.ui2.resources.Fonts; -import org.saturnclient.ui2.resources.SvgTexture; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; -import net.minecraft.util.Identifier; public class TitleMenu extends SaturnScreen { public TitleMenu() { @@ -72,9 +70,5 @@ public class TitleMenu extends SaturnScreen { }).dimensions(s, s).position((s + 2) * 2, 0).animation(new SlideFade(1000, s + 8))); draw(saturnStagger.dimensions(((s + 2) * 2) + s, s).centerHorizontal(width, height, 0, 8)); - - draw(new ImageTexture( - SvgTexture.getSvg(client, Identifier.of("saturnclient", "textures/gui/test.svg"), 98, 98, 1.0f)) - .dimensions(98, 98)); } } From 0cfa7b81ef022391528844ff7ce7069949a8440c Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 22 Feb 2026 23:40:39 +0100 Subject: [PATCH 06/18] SVG mod icons --- .../org/saturnclient/ui2/RenderScope.java | 8 ++++ .../ui2/resources/SvgTexture.java | 15 ++++++-- .../saturnclient/ui2/resources/Textures.java | 2 +- .../saturnclient/textures/gui/mod/armor.png | Bin 675 -> 0 bytes .../saturnclient/textures/gui/mod/armor.svg | 1 + .../saturnclient/textures/gui/mod/coords.png | Bin 526 -> 0 bytes .../saturnclient/textures/gui/mod/coords.svg | 1 + .../textures/gui/mod/crosshair.png | Bin 1027 -> 0 bytes .../textures/gui/mod/crosshair.svg | 1 + .../saturnclient/textures/gui/mod/day.png | Bin 294 -> 0 bytes .../saturnclient/textures/gui/mod/day.svg | 1 + .../saturnclient/textures/gui/mod/effect.png | Bin 2580 -> 0 bytes .../saturnclient/textures/gui/mod/effect.svg | 1 + .../saturnclient/textures/gui/mod/fps.png | Bin 478 -> 0 bytes .../saturnclient/textures/gui/mod/fps.svg | 1 + .../textures/gui/mod/freelook.png | Bin 959 -> 0 bytes .../textures/gui/mod/freelook.svg | 1 + .../textures/gui/mod/fullbright.png | Bin 697 -> 0 bytes .../textures/gui/mod/fullbright.svg | 1 + .../saturnclient/textures/gui/mod/health.png | Bin 962 -> 0 bytes .../saturnclient/textures/gui/mod/health.svg | 1 + .../textures/gui/mod/keystrokes.png | Bin 3226 -> 0 bytes .../textures/gui/mod/keystrokes.svg | 1 + .../saturnclient/textures/gui/mod/nofog.png | Bin 282 -> 0 bytes .../saturnclient/textures/gui/mod/nofog.svg | 1 + .../textures/gui/mod/particles.png | Bin 1087 -> 0 bytes .../textures/gui/mod/particles.svg | 1 + .../saturnclient/textures/gui/mod/speed.png | Bin 1032 -> 0 bytes .../saturnclient/textures/gui/mod/speed.svg | 1 + .../saturnclient/textures/gui/mod/sprint.png | Bin 961 -> 0 bytes .../saturnclient/textures/gui/mod/sprint.svg | 35 ++++++++++++++++++ .../saturnclient/textures/gui/mod/zoom.png | Bin 1736 -> 0 bytes .../saturnclient/textures/gui/mod/zoom.svg | 1 + .../assets/saturnclient/textures/gui/test.svg | 1 - 34 files changed, 69 insertions(+), 6 deletions(-) delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/armor.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/armor.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/coords.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/coords.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/crosshair.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/crosshair.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/day.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/day.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/effect.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/effect.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/fps.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/fps.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/freelook.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/freelook.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/fullbright.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/fullbright.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/health.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/health.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/keystrokes.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/keystrokes.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/nofog.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/nofog.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/particles.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/particles.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/speed.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/speed.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/sprint.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/sprint.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/zoom.png create mode 100644 src/main/resources/assets/saturnclient/textures/gui/mod/zoom.svg delete mode 100644 src/main/resources/assets/saturnclient/textures/gui/test.svg diff --git a/src/main/java/org/saturnclient/ui2/RenderScope.java b/src/main/java/org/saturnclient/ui2/RenderScope.java index 5cd7f59..1f846e6 100644 --- a/src/main/java/org/saturnclient/ui2/RenderScope.java +++ b/src/main/java/org/saturnclient/ui2/RenderScope.java @@ -9,11 +9,14 @@ import java.util.function.Function; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.saturnclient.ui2.resources.Fonts; +import org.saturnclient.ui2.resources.SvgTexture; + import com.mojang.blaze3d.systems.RenderSystem; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.mixin.DrawContextAccessor; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer.TextLayerType; import net.minecraft.client.gui.DrawContext; @@ -224,6 +227,11 @@ public class RenderScope { private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2, float u1, float u2, float v1, float v2, int color) { + + if (sprite.toString().endsWith(".svg")) { + sprite = SvgTexture.getSvg(MinecraftClient.getInstance(), sprite, (x2 - x1) * 2, (y2 - y1) * 2); + } + if (color == 0) return; x1 *= 4; diff --git a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java index 438a190..937a79e 100644 --- a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java +++ b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java @@ -4,12 +4,13 @@ import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; import com.kitfox.svg.SVGDiagram; import com.kitfox.svg.SVGUniverse; import org.jetbrains.annotations.Nullable; -import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; import net.minecraft.client.MinecraftClient; @@ -17,6 +18,8 @@ import net.minecraft.util.Identifier; public class SvgTexture { + private static List svgCache = new ArrayList<>(); + private static BufferedImage renderSvg(InputStream svgStream, int width, int height) throws Exception { // Load SVG SVGUniverse universe = new SVGUniverse(); @@ -52,6 +55,13 @@ public class SvgTexture { @Nullable @SuppressWarnings("resource") public static Identifier getSvg(MinecraftClient client, Identifier svgImage, int width, int height) { + Identifier id = Identifier + .of(svgImage.toString().replaceAll("\\.svg$", (width + "_" + height).toString() + ".png")); + + if (svgCache.contains(id)) { + return id; + } + try (InputStream svgStream = client .getResourceManager() .getResource(svgImage).get() @@ -59,9 +69,6 @@ public class SvgTexture { BufferedImage image = renderSvg(svgStream, width, height); - System.out.println(svgImage.toString()); - - Identifier id = Identifier.of(SaturnClient.MOD_ID, "img_svg_render_" + (int) (Math.random() * 30)); IdentifierUtils.registerBufferedImageTexture(id, image); return id; diff --git a/src/main/java/org/saturnclient/ui2/resources/Textures.java b/src/main/java/org/saturnclient/ui2/resources/Textures.java index cdaac79..35a238c 100644 --- a/src/main/java/org/saturnclient/ui2/resources/Textures.java +++ b/src/main/java/org/saturnclient/ui2/resources/Textures.java @@ -53,7 +53,7 @@ public class Textures { } public static Identifier getModIcon(String modId) { - return Identifier.of("saturnclient", "textures/gui/mod/" + modId + ".png"); + return Identifier.of("saturnclient", "textures/gui/mod/" + modId + ".svg"); } } diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/armor.png b/src/main/resources/assets/saturnclient/textures/gui/mod/armor.png deleted file mode 100644 index 3d1c75e62fe47fff5b6b3f0bbe587370da0762b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 675 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz07Sip>6gA}f5OZv>fz{Kn6;usRa z`F8qw?c6|#w(kcYh#4)r!>P=sVR+=slWTJ&6OvLCf|FF3)w=c{Ff|E!<<@yoSM3jH zmx_w2eOur2%Tc?pX06?O?bdTK=J>sD^Xp&N&fj`#?q+NC({?+xQopYcTfI2tcu3vu zpp|c?r>Z``Q6qQLbUu$4?}lXgU)k?-?wpQ_*D`;>Zq>7`r?Ba`q}3y^1WY- z_cC0+=#j@|^2k-%W7DAvUnM%yW|kH0<(s9EGG}M+ zxUO^dT;Mw9IV-R7-Meo!gFQ(4=!*c$v*!%gG0Qwz9ch;LB{h0-;-z=CR`ED zDz-ixylHLM!KckP1^gZ!*rUK1Y8|N9-ub7mtsu4};*T=Zakq-g?@QKCxNGuBJum#= zlmhWxrV8#~?y^qoSDk8YQdDll{dCT27WNBE87G%XZoR>n=9|Gev-IfM1#f+Kv0v!> z=A-pjd(!>RzbnMoD*ik$OLc!+y;^Qq3Y%H;lft%Fa))ySSAUUuAfLfES9!Od#EI?8 z4O5$={>}N9wD`V9T-xqGmb!mSeJwxKf8WPkqP=6b \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/coords.png b/src/main/resources/assets/saturnclient/textures/gui/mod/coords.png deleted file mode 100644 index 5af14bf85154a3ec9adef2485e203130dd13b8d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 526 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz07Sip>6gA}f5OZp5{R^jR57!twx zcABjpvm;OIW)G2&4(=t(9Wpa_Fos&`HJ&hCQN*U9RLHEd&Vko8sE}d7!Ud6biwlz? zB~4~`hKppM+?cNRt@`oJpOU?7CqowG-j4oaV=Qx<_XD@qr(VCLi!o&k;!QbEc=yW- zF;o^j74$#USg*Nhqtl}^qB-`yLg!^KEY7^WO6Pm?j*~?j3hVcZ?w|f*`8RXl;@0~0 zZw*fOEPoNfuz^2{k#)=CTjFWk1v{8NdkeHqK5H!?p|v5H^@i%^Exz+N#fP6g5P#dC zv0jBKm)FnC%>6(kcW0!T=h*{hOnV!-3;h$s3zCk#Fv{E>J!Qey*am(1IqND5Z+1@H z?Yi`Kb(4no0^=Qe_Lc9ZFm9XEqO4%qmA>vlR_E6Dokl_|w%l10PB@qUy>(93Mct~I zq1xlz%4fM(Hj1@f-;#f!JS5K3w8-ZJYt@uVdp@1ATI(4hbJ|61#hTrx7Fq20*01o& u@`C-23G7$rG5 \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/crosshair.png b/src/main/resources/assets/saturnclient/textures/gui/mod/crosshair.png deleted file mode 100644 index cd208a312e25e9bef61db26c5f02d583457009a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1027 zcmV+e1pNDnP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NFZAnByRA>e5nmdliL_Y9`;%uM@k$HdH==7RSNLQz}4=7CVcRT-VfC zg5PaT(p$Ner-(n zqmFcrPsDbLAun|ph&#R@n^Rl1@8OTsZBeC(!54pZ2&s@h{1a*O=5wQP1%mY zO|A6Vx$8H5x6TC6wd%B;r^0Lx=+Mbx+1}Kg_F6KnHUOQNS!9ca&8#WywPadt0DiGh zx6Q;>f`{gZv)4M9#u~Yq%X)x4hYni1Ziv*r8%2-T&`q>DsoXMT8vjAl>`zMd3BAzV zkNPBlW*@60LFi+;nFm`6Kp=qT9xeV2VGu-f4|kJZX!h~C2|_*LPpZip96Htd1IPdW z6I1#=B)y^8$)8-SC&mTYp6pR34zx~avGa$(WL1W2$!78KxqYIfqlb`dr)joL-ZtEX xYp|9dx+@2O;0y$#v&vfjYLJPzP1N)R{s2chGlfVd^7sG%002ovPDHLkV1lRc%Pjx^ diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/crosshair.svg b/src/main/resources/assets/saturnclient/textures/gui/mod/crosshair.svg new file mode 100644 index 0000000..bb0cb50 --- /dev/null +++ b/src/main/resources/assets/saturnclient/textures/gui/mod/crosshair.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/day.png b/src/main/resources/assets/saturnclient/textures/gui/mod/day.png deleted file mode 100644 index 5fb33522fdf647e710b98dd9e5166550181eb2e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-&H|6fVg?3oVGw3ym^DWND0suu z#WAE}&f8m#d`$)dZVxTxwBPMtSJ0O(B_iy!P)S$z=YCng8NZwsNuM!dl>P8P`N;XA z_xr2Z!3eX!KUQO3paJ@>;J6#8+D@MlVkgh^55-u-J{=J zoWEuMl|O!p3zyE1uj6qYl&H~$DwO`zUc&UaLv?M65^4&Oh7%rBYB7O pi3WS;SE79WhKFBi%OvGiFx7jU->Vw5-xKIZ22WQ%mvv4FO#munb;1Au diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/day.svg b/src/main/resources/assets/saturnclient/textures/gui/mod/day.svg new file mode 100644 index 0000000..9432885 --- /dev/null +++ b/src/main/resources/assets/saturnclient/textures/gui/mod/day.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/effect.png b/src/main/resources/assets/saturnclient/textures/gui/mod/effect.png deleted file mode 100644 index ad39774d89b2e83a7f92ad1717855ae89aafdbc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2580 zcmV+v3hVWWP)>zI0K4gMYM4s zNFK=hy@yDVDT#!Rhr`|BKx7mHfH$r+WEd$p;rYUi3`2?&oEm#-Qo;{31Fi#Jx%Qe2 z3BUC`UmrY<+gL6m^x2Me_g&}&9?yR!BMLl3P2WvEgdL3E+yUogJjn^0M@`?&VFSJB zd2aOc^2BQ@`fd&Zs(YRr{hZP^HLVS&iqG*qHjF(2+dAlH**0Xjc=lgxj%E?Z@ZT<> z$iJZl*C!W`^xGvZ5qDv)gHU`y8jWjz(TWK--zK83Siok}L_g9vd<~B&7j`$`y~PrQ zfQR#%yn$RtzV(Wmdw=U5xqUc0J8Nko&S+%Zh3z_H*G|zMv`?-B?q~&sA)6cb5erYw zo2GT`J^B7@X$ioL=z9hZ?L@G4+EGeyqm^SjY z$uR*cgAXTOYsoNTIGnleASIXvDu56hJoH|-qy!V7a%c~pzb7S_0F}d`9kj;yp)nLF zT-rQVLYXlRw`AJKFbu;m48t%CW5r}y*5iB=Z`{Lg8uD&Kj!Z>*)|K6^Wtmbk8XR09 z;P?j9E|-br+O>*|?}38aef;CN)}7+)x?ZEX^mBY(zg{ygr+i*tS<7iu4x6F%!x+c+I@9s{JH$l($Z@8 zt(XS_1n*TIDlkt`(_WzNXHZ)=o$3ekO&tVttxVL01o*|y-#{}d*GFCyd z00m9dp7>L1cFuYj8jWuwUo#fUPyw>qeJf|E0I}oo!EhB^0LDrfBtV*L_ZicWBdNYU zc&?^)pD_(N1juUlt(d_j?l>hQMAgmySs}S@@sUWZ~G?l^_0%U?z3h;?;Ln@SwDM0t158LWfAMnFf zgW-IP_^yu_PJ@MLqvDNd_%&?&!`C#NZNxD-{9Uzc4Q5}_zOzPNHe^f> z{8HF+RvAJdJCwF<|Ktyz%}Dc?@`FL&kVuxbW~4 z|H`%O<%p5yxID#%jQn7@!F-Jgrq0MCNaicbN%&Dx>EM@UPkqkkNOwB2rnI6HIe-sM zbV!4TtJ#)UhjYI|8Xc4@4KEs`$F(M{)A$%jAAZHNL*oFXIqg{e$J9fd6h0@U#p!A? z(m>kKrPg+Uw~M57WXOT{uSiipdr7>m3o>Ltu6>HxN(pi=HV=JfP{#uKUHXm+19I>6 z;`SOF4al?)A6rpj!27l&Ms+EBqRk8B+NW5rE#%YtnvBPROtlw3LlItYLqgWxV)lwSls=o&jCQ+4fX zG!SGnjQ2~b1RJg;RtwFsv2ib&hA>H%U`xwGQd=o|MrA6R1gI7qyTn3P5<5tZ2Fg`n zDhE~Marc#B;Zrt#3GX{)6WoRNDLme49`^X$+%;_}t{*I0@fZwS(;f>iOV*t3aUFRb zYQh>ShA{Y9#S}9O79JL&4e4YXdEC!XG85Bc15Mo-m(ZCm`dM)7Pow}X0#woTa3HgT zu1LPbMtepISbL4ciu{nKC8j13AQc)&(=1HNmb^b`w_nGu?d++F_D;8o`n4P%a|7?l z{MXHfwq%qAWD#jzXZ4Hl^DD$9sdaN|BVj*GzF6`UT81!*>SlkA#Mq>uRi3+c^TeSQ zd2Mu!d2FNN;(H|uP*Nweqt3OzDK3it%C!!@m_tR=A-f-<8;~FC*xC_q1a-)xd ztfr1=78d#amypxJYq7!cHOTV8t?0rr@a5)W86__m!-_+7uDuJ_!CLJ}V;|o3Bw2Z*t8w1KGibUPC*)MLWSj=FbzzfFWw9^o zn`6I>RIC7JACN6?nYAbz%#M2G}JXILzNND zz&q$9jZ8V|u7o0HW2scmcZ2p}I8id&@sc_9g_l^Bcbte23{ zp&;7;X|=D-c$NUU9ih%X=mYZF*QR}>AgxC9hLnS}4P#9Eq=2+3@`jX>C_Kd#5LE-@ zg(%eu5z@D+s>nzO3)p7@>HB?HY2O?m-P_w?#yc2ZgQhwaEom$lkmWER!$aT&O$@x| zOf4AE!G^B9z;9GCq=H9>31&0!v&W&K3@hI<21wheE&dKFEGVF zfNQ@}Sz8~xap(NpY7r>|!yJxN&_GFDAL9|={Y4%0z|(wHyX+VdV17Yj!MTL3q$ryp zNDZc=aqT4;%L4m_ferH0z^@Zqm9{B<8lOt|p?TMvn)a1kW4+5;^3(7(Jbqfz_EQp8 qD?oh&!K&!{I?P-CM_S->>HH5%%+t;TV_Fpe0000 \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/fps.png b/src/main/resources/assets/saturnclient/textures/gui/mod/fps.png deleted file mode 100644 index 0daed1674648db12c476379da0550c463a13df75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz07Sip>6gA}f5OZp5{=Hcn$7!twx zHq?-d$xz@-=Z%QSAI#j`@(;OlT9~;Heye*RT+_IAYg6yujKtix@;Wt*^ESJSiJd$; z;WXIUAN zN5Ko;eiqu#d`a%Ztoa+|S<0HGT1`+n>AazYwXAI_i^b*$q5shgX(?W5nGLHeAM#&EG4W=#^ zzT4j@68(^JtpC0J?!D#VjI#M{`ue-Legqw}|6|PL_p8VKaOBP7mUD_2cVsE&#Lsvq za!h+`dVBXN?TXG#m-O#ET=>U)Pv \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/freelook.png b/src/main/resources/assets/saturnclient/textures/gui/mod/freelook.png deleted file mode 100644 index 9418d12a8d19800cf074e01ac0c7c25cf48be101..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 959 zcmV;w13>(VP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NFDM>^@RA>e5SiNo(F%Z559)JSq zQbc(JLQNgfN3?qn5%C&P`k>T2K$JQ)k@607i4c@YksRMgJiFtuy}!N-MmN%&XU6mE z_1}51*g_#Auv)E_z#E6lLeg&2bcv&Bpl*8$ppZ64-$FS>AahQk7!*}R9jgGcZ4p^l z5k~X~_#Jo;90R8|5g5zvHO7zDWe&{c$odX=DD63AG?U=LI)#_m;-BOkMl57c$EY+z z1@QY?Hj;jPV#hh#vcP;z~36#9CqL3>igj6 z12udF^TyX&EFjzHPQ)C5%tZrdiVx_u3-;NQmkf~`i_mZ{eNC%-NjDvifaqBdvcCK{ zH9UwE5Zg^^tG6!ROAd_0c_qYzc8T5K%-X^C0c4+mAAvir{|DMj;5lqAoGfpXs!*b! zUk)UGiQqa7*)H%Hcn3@Y`>3-keuuW!VPMy*5LmPVCItLueRS~D9aV(&)kb$zuR>ta z3Si4ojlnMni7_~CJ@ix7L159V5Li43V0Qqt)8-tqLmy&-e5zw|G8`b70U{t`|$~g+)Atmq{M03>@p=#Mj9RY1CvQcf00xnI&C8lU} z5kt=&fY#Qy8o{O(NuLYYmA#F!Kon8#LFNi5`zoP|;FqwcvYwsE%N&%rc6d=tT^6;U z<{V(`zu@(P5&75_rd$&|oq53hbV!=A=+yyo`!|&j0Ukid1Fw^e*9#_4Sd##uZ1PN{ zi~M7@1Z#%wVRw~2-3Wh zR(b^Cc<$4pc1QXaf8yV1A!6|Tbj}qf{U>ew?CF0mA~?v_Jf73tC%!~*m6#r31D25@$|`_kgd#ex h(;FDaZHP%D@CUy;9|+M{F`NJZ002ovPDHLkV1ie~ncDyW diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/freelook.svg b/src/main/resources/assets/saturnclient/textures/gui/mod/freelook.svg new file mode 100644 index 0000000..199e319 --- /dev/null +++ b/src/main/resources/assets/saturnclient/textures/gui/mod/freelook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/fullbright.png b/src/main/resources/assets/saturnclient/textures/gui/mod/fullbright.png deleted file mode 100644 index dfa9f7a583088a07a0740fe01da8b58388ebc482..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 697 zcmV;q0!ICbP)3+h!>OxSe3+( zXu{Fcdc@tpOXv$29s@X`h=>oM!Q^Ku)FegQ?)Hq`vkaLp>C0?a*Z1|`s@g1T(4avQ z0As)tZLO?s;GB4lm8@<6HjRMItZtwY5E;NVU@o-);EwnzO>_YH&q}5*H%x%dh7qt4 zcx&~wzxW!DDL`h$VrQ5LU>4X1_JCUfzg0rs5z!U$K*xNa2DX9U{2ON~Y|7X@*Ri_E$qx{9 z7dRmtKY)kXWdJY_{Bj6>lGOp0v~~2Gh1lF5HTh|s%^Y6_%`C709GU*#fyruFUnI2c zke>;#nQ=t)s$uKDZR~-aFJQaq9PD;lwtf<8cF&iv-!=A6Q)E)FoVG6Ef$1lAdyY;C zKQD~^dnW{0_xKOX?3_%>#h&RW4^)n&5(1Wu{Ri{?V1WOXItbYRUjZ%Y2)uRLYa3N2 z-a>CY{vSsz4rpu>>kzL-BUXSwTd%+z3k7T+8M`xJA}!mn9N{SNA-k!;TaK-2*!sy# z0jG|L#UV3q$)5l>s%8B*sRy25ZdVWKvbLAbo)`QC?q!z&8cy59WEf71gdS0$FSVqB z$C8Yg?~{79+Jo&ve%rF!hVzv=t|XxeOerTMwvoGC9w==>dewK^P*qBqFsbi4W2O;N z>#_>v3tI=;W=C4s;$msBS3zmIC&Ftc4 fQVkk3$SnQ<+wIF!@{WD(00000NkvXXu0mjfk#Rfb diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/fullbright.svg b/src/main/resources/assets/saturnclient/textures/gui/mod/fullbright.svg new file mode 100644 index 0000000..3e8360d --- /dev/null +++ b/src/main/resources/assets/saturnclient/textures/gui/mod/fullbright.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/health.png b/src/main/resources/assets/saturnclient/textures/gui/mod/health.png deleted file mode 100644 index dcca15ca6145bcc8d171e707e4aabb03a82be5af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 962 zcmV;z13mnSP)OT9K@8^n097M5h92Lu`sqy#H`K1Cx^e{F6wnvb=T|MPTrr?;=Ob3fBsW< zKIL2qC6rJ?2_XZh0M-DPfcwBF;2Tf}Tm;qugER0A0oJQ+owz=U+x}Y(49YWsQNU%= z;Wuy&sA_<3gnZ054K4xIO-Z0Fu)_=Z2G|cwRqu2J+5vrlDZp;vt$cq1n}9NpuMF5M zTg0~um@E$C>L~7MzybM0FK9c^CTkMifGZ;T4AcPSDcW@gHfop{jwk_pj_E(MZ7|;y zeC101i`P3{v-Cui#4{TTDf9O^s(`2BIOZks1Q^~3zG~pPmrQccXgEbl^vW94Uyv+f5DAT;KqvOY4O=<3kw-xWK{x zY49M-by zwBC+09+h#i3mm{QX+0EYTrT5b7dZI;(w7#xu^HZlJmG=%zz1oqDCBfg4zpaK0Om;J z^@f~Q$jK6F0E-(NyrL8t`_{b zxS<9IT_6AsOVhQ~*8*UeS3p=)bd||^mPpH2U})CH3)J{KFtKPVlXXmz2E+Wul0=0F zs{oG8U1f6o@v0vr7aUStQ;&PeG+WOA6M&D3eWJEyntL4WsvA{PGMu&2YL5I?radq2Un;8>?{uMp^?L<;1dPdn za~$y4JG4&DM{RQ80l-}a{;A=Rc^qr=wQnvz#C6|J;l)wiZ~d73#G&p%=Q40rUh;dvD#2IXk`I)^j~vO93!X$C?PXQ?GO_5kMtyPfw+5 k$>873E|{BU39gy&2VctvN`ERT%K!iX07*qoM6N<$f(a9{jsO4v diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/health.svg b/src/main/resources/assets/saturnclient/textures/gui/mod/health.svg new file mode 100644 index 0000000..491bbd7 --- /dev/null +++ b/src/main/resources/assets/saturnclient/textures/gui/mod/health.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/keystrokes.png b/src/main/resources/assets/saturnclient/textures/gui/mod/keystrokes.png deleted file mode 100644 index da20fcdf594e6824899c2a52b07b0e3614437159..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3226 zcmb_ec{o)49v{n)wf7>H89Xb2YX`F`g|G%!U^6va4 zyZkscoAlV`_Qk@U`m$TJNk)@f=MB8EjEqck(qYwlfr!3{?+I~Bg=0xm)xj~CfiFz7 ziNhPlVopnNGUMiwNArZ}_`6>$yu}tG-{DvK(Mb+$#Rj~Iq?C(d>f^guUI)(m0^)Si zB9uyWzMWl^Wek7%-Ijs9VN;thlGOANHU6yqDYcO;`>aB-en`y1Yns=JGqE=%ey7Q9 zkEAW>{&;GkbI*Kt$=Iop<{rO&Gh#bcYDhvDa&%1jBpwfF_0uKVgiQ=4ZKCyF=68xA zpT{m?EMC$-w1tf%Io3^!*lu+i_J_YFMe8%#4I@g!N2=kvo)jtKHO95loQtqe_TDB< zQnGgHaDhu!Nj(3CXT!8`X6<0cXiqc0QU9i9IUncx>Z{IHl=YdY0Hh z80G$isq_7@t4g}Mi6)=oGLz4wk{6K2JakCcLC~|0muB-p0FDbxAEG8n_-Vm$YUy~c z^*1=~%7blA7mhphV4IVM!66Vmr~ zTZiNL0@c>U_t22G<(E}7KW8hC9Bp`k7@eTQwD$fA5vplt_$xl8`QygYHGI+I;;& z?;Vwa8{B^IIa_c*r5}2l)e`eDxuxXtK2==f91xzFw)JMmrJz9NCC`$eH(6O}>IQ;; z`eOeD)?8>M|8nSI*SY17?mlx&UZAOY!I!+i>J|6#i^U5@U&%52yR|;rIk{m;L*av# zj6DSx*&U9ioi_>!7Z-h2$jkSJ($sta-v(f6ujUJ9kVQYU=i8e?rE% z){*&G?*h5(x)rGUH^^kNuARDtcL6oB3phCv;az7t^dcd%UeN2;S((y;61K>)6y8v#LvUcDdzvcnC(T*}s$0i;5BaBf4_&;U@ zWb$5r7h+SZ*$|a9717LD^!JOEa_LDu7)w&$LUyrjXVLhJU%HQ*3%*p7wA-h0a+*n9U_S1PnoA}Tj(+@^kQ zQXB*Y(a9Vuwv;vn&3SI#b4H1MU8+<3Wb~N2o|&%eAm~bi+&5()_v(&Xxv%~$*kbA<>D=DqW+VkCmpOV`w&$SA&cg#x{U|P%f4iuNDP?3xGdmM49EB4txFR zFG>rlvH>idSTzTl0RDrhRQ-cLMJQ^bfOw~sIoJWfXAB06C)qNY z^Ope4Zrpkyp-xaXr)ccfTkOdaL-YjI3sFJ12n>G4dY`OjOt<%j&5sT{r>BaI()L$( zvcL|x5rU6dD|6fm*m)MG2o4{R9EY68t3j*GXTG zNJkqyFk6G`K5oD1#rrB~DA!R($tfb~tr`Y+u#f`_+B}}Akg`^y(hwjLXd2U@8j&7D z9QvUL94@m=cXag@!C%kMFSPseqd7rZ$;l&0RZ})fL&?bzGKyE^&)1glI(QqE zgsCUEimxu6%G)WNvkVL zH;X>~GDttt!l!D2YO5suB`p$7aN^4>D0Eqg3&Vi#w*nn~Et@Ba<=ZJzTtcSDp%mf> zCzn4`C~p+B_2&KB*kCBieS>8Bu1Vy21!0a)t;1A0Q}4P_>liq^MLE)-MhaN6={esz zh7Aks+bB3S?+}<6OGN14N{&ONY#fHJu~H-H?rEE;w_jPq$c|~O=XT6F#3ja#n@Hjw zY{!IRYtE}tU+->Xa$_{*M}yb1PR%uz@@Nq4(&`%~xaTzxk5O+}vQ_ireV$kvQN(3MRkMQW8q~_(>bNG-esMVlPOtHA8)X$ z?=Y6$)7sNw|chCw!EiYWYzjWVr zr1<5b9&tA}K8tPJ?dq0qsK7!)BFJrS1H@O3%AW?-AJA!?_pTNj@G)g*S^+UtD)rFt zqAhA8-4=mp)b7^7`VTGez2?5f}( z^HHvY3|od)hR=Q)pM%HKFEKY6Xh=(y@W$iwU2k}{CbwEdGZ*xx((V;=l%Z%#rmfNV z41%`XY=}+e^c@;+2Q`>=oPsZOm<4Z9_k($L zW=}bdHc^Iw1I?2kPy$aub4KgQqm$zJh~_xishTfk9E#UK5YZI)iz)fPQm \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/nofog.png b/src/main/resources/assets/saturnclient/textures/gui/mod/nofog.png deleted file mode 100644 index d7dc168035cdec9a615b34d443177d2f2bf4cdc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 282 zcmV+#0p \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/particles.png b/src/main/resources/assets/saturnclient/textures/gui/mod/particles.png deleted file mode 100644 index 3709190894dd0017a277f52e44154ae6c21b2c38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1087 zcmV-F1i<@=P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NFsYygZRA>e5n!QpKK@i99EXdGE zLQH%GLoGKTgHWG<#1|maOfyrljC>IY){+cDAR!k`Hi_v%8lQEWm$Wur0~F*%QOCv|&#sV-!$D5#mWn7HckJ#(J-Tf5N&a zM#G9YOQhh1dg|(P_x-3bD@RpOaZp%t$vDb_r%aGP8Owy zF2E=Eg#>Gtq%SgvKS7*^Nnw^C;&d;M}{>}04Pp8x0ju%bUHL%w!FJ;{azoa%a@6ZS3m6`Tjz4Ts_BJY(dF@eWkXsGaux$kkj=CI2%4 z%iYAb5|Ytl^fkCzk5OAhpebVY4ziGZYNVhIa0k@!uWLXGZnP6h`zb|u@*!Wl;P6+8 zR1ua(P;JE3xy;$*1KkwC5JCHNf~z7uwDRDm&uGtq$ew6>pq5uy{0_r`@)Ki!iK~o5 zON)Kl*cg?5WVQg@y#n<~PbhjG)J~x?b4!a|>(3})etF0UiYtMpHlc;HkRVKd&)EsG z!AF8A(Hyj2#C%{3^mOvD1w-gzu%}I_g?x_1IX$fl*0ECx7cJYO63B&6?X*%C?S802{pqTDW8)w2=I`YyAvD6S4DSGz7$E z9W1?qO12jC@8n2=M_>*PhfX@R2NsP{7aWvi1+%-7WwC002ovPDHLk FV1kjz=gt5C diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/particles.svg b/src/main/resources/assets/saturnclient/textures/gui/mod/particles.svg new file mode 100644 index 0000000..f4addd6 --- /dev/null +++ b/src/main/resources/assets/saturnclient/textures/gui/mod/particles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/speed.png b/src/main/resources/assets/saturnclient/textures/gui/mod/speed.png deleted file mode 100644 index 8ad03eb9be96cda1310cf705ba57b9eec6e02d61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1032 zcmV+j1o!)iP)-+xSTI(bdF=E7s5#wJ5&>ffsYyuj9Tfl4J6Yv>m0d4~)G-fu?HBkxxIs*%Uf% zj!&Aq5GZet06GDyfR~O_Ux5q27GMrA45)VG_B=$g%^Lg7kv|1i0~N&zV!Dh5xCtx= zs?v=Ag^+YyE*$~x0}~4wKo?*S(CQd9C(1I+OB;wYW&rTr(Q7vL+REoUh@QZ8C$EDq zcqEIt*#vS}!wv##MGl5b=~g;Q5Ph}WhKImNpbzjt@1|v#-w0d|k&n>|d^Ej!XZ6)A z{f~q9xvs<$DYO;o;mGXE8Sdqh0>EkMsY`ipN&qCuC1A?ttZEWi-VLTNF`v%04p<1>RG@FJ--Mod|1+~yGg099izI|>> zAeVCtWW4_TU$6jyv`E-9im?!8aj`W|x~rwHC9K$o=dswgYh_+p5c#@H;CHd#_6g5Q z7>P-W31FUlZSV=V`OeOz2w<0d-Qp9@mGEk!#6j{7!Jj?OW~?;|MHcy-(kd$V_dI8t zvOeYg2;KD-^E}c~HvhOY05-_Sli3`s-sp%)+?*#c8E=7)T!mQUuJ zVNs^Ltl+4740xw!+xzd#aBUMMkgyxba@h=iu6Qq>g41d^l>@aY#w^_iCE5wVASdMm z)MhiWT$jhzS7szi1i%d7oO~<(k3unG#E22&zs66y5_GVucokv*0000 \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/sprint.png b/src/main/resources/assets/saturnclient/textures/gui/mod/sprint.png deleted file mode 100644 index c1c507c090466ffec1a84e9d1fd1b5264fb47a75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 961 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!Wi-X*q7;m1`sRwd63p^r=85p>Q zL70(Y)*K0-U}Jz!h%1o(KcFD?zEUvI5!xj|e!&cuGj9H#{(q-I;>x$rW0IyE{gHm` zkK;Gv4gXa9{#NW-BD82r@|m=mlN~l)QJU6Q$H2g}$kW9!q+-t78`b%j4Fnhptlu75 zawvp%8xLEm4eR~?hZ`#T4hhKeEB1Ot{^H>5lz)EXWo(wW^r^p-t+GF_K7ZZY<{T6I z`$oAR{ETrdr@J{=-gNNmTz71ce%1Z?G=qc56}F#;tPhkQC}@mi7h+Irh+z{lkZ5?A z^;BBIEn!DooV7wlSCf9x2cyv5MLaQ^cOc!wwi;$9EUqLrN7hJ8993vrOtbM(DPx-*#j#w&PGP<+422w1-I7?4wsb{#WC^k zKFm?dVKJ(Fc5scA+)}O3@}Dd1A6$$q^$A+1d#rX}mMO=9%bBG%7S<0Ec1H6uDbz`p z?=y1FF#gb>v8Zt8G2X_Fe`~hMDs*Lh>bu!$xSg}YLFD2`_h$m%_UE#mQ2G@kzw;*F z@#kwKXV04ZYl4aZduwdzmT@P2ZGP^EmH|gk(xn~r)#EV~S zV&<8H)rAd$Zh{M$d1tsjkri+i`OnF6qWa5|L$k8$8It+$w=sMuBf|#;HxJ=| zA8mJ;&YS%Mo+%>bUT-u*9%fsRIG5^^Pl4sq$SuSiVZ54jOW$^vk z?HLZ`2Ns%~DztXc_$04zR(=Zmf}kHMVz=j2)-axX(J1$V@wD7I^9wf)|71I3JE#1> lox?xbCtPH + + + +Created by potrace 1.15, written by Peter Selinger 2001-2017 + + + + + + diff --git a/src/main/resources/assets/saturnclient/textures/gui/mod/zoom.png b/src/main/resources/assets/saturnclient/textures/gui/mod/zoom.png deleted file mode 100644 index c6969ae522664a35d9cfeb01a30ce4867f44de7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1736 zcmV;(1~>VMP)zqfJ)velIo1HesEVyF3WDiE%4 zZ~HOe@EVNY1Ncbe>;}e#0H~EWQ=feX99HQ0?G*}QHaWvkCofk3G%VfUghs34Hf@E5 z*KG1`m3=Dt#Qou^iBbzhJl)ApbACM2`)&a^d&=hxFQ!)87R8wEh2pDDnQNuUCg3Q^ z4gpq5J_TqPfwwF0TgIvzA(^>dS)qBe-u@~P-sgGL=QSy*pkLYCI6SN1@MbFbAE4I ztBXJFVi7k3{uD_rw+Bwv+c)2A8HG4omwTkg3@5V#lVL13lMdo~Jb)w&$5 z{KH~F3&}2$E(>CjjupWKC$qgCpQ+UrfOo`wrJkG1DBGf(7=c+L9IWSq6J$KOa(t?xar%xa8zvX0aNOo}y!ZjMaqn@qYwMRBso6t$q zu*}JxlkA!pgq!^GQX#`Iso-S!>C;C1UprZ-OI#O&utJ09k{t^^dY)Wxvi$V1nxf%z zCwoe=K`{tF)8J?7xm(%?YZJh^>Ff`9MY4V|2;bG<1N7Wl&ua=!mY+U1ivLw73#ZgG zVi3Nl!AHA;QH3(WV+&4Ly*@8UpJ7fG(%~aw5MHmrXF1uck_|67VfBUBbt#v$wA}Dz zEYcH2U`>lgsoKDzD5O>EVr@2b49?X6fSV;7ACq{M4>CH1{U}+FXvF{3;{$Pyao2}d;RFhtqFD4}Se>!RTj>P0+hv4yOkOLchD0N;#j1t`}A{#Bjf zqxU-Co=Hw`x7DFu;Xf5;;4If8u-+jmlor(Ws)dRoAs)O99GW_I-PHmQy~KR5TC1jo z8>dWp$PPF8hVBwpQH^k%x8k=r|TL)J@{iIxGxm@TA;6p|Eky*YBobIB1SoV7a zJsDxHGeVczn0tDHh0VmGk>yA$+C z`cl*ZVT1sss&{D8Ve6_2yA&HepOjWD~u z8=-y42;^?GhHlZ^j69*KjDw6-_kWa8LnBmFV+8vRf?-NhAHkkRn3rJ$yM>AhEzx@$ zMS*GxnMTlE \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/textures/gui/test.svg b/src/main/resources/assets/saturnclient/textures/gui/test.svg deleted file mode 100644 index 15e0aff..0000000 --- a/src/main/resources/assets/saturnclient/textures/gui/test.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 44c0b69c4d0a6ef2117a369360f62123fea599f2 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 22 Feb 2026 23:59:25 +0100 Subject: [PATCH 07/18] Fixed keystrokes --- .../java/org/saturnclient/modules/mods/Keystrokes.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/saturnclient/modules/mods/Keystrokes.java b/src/main/java/org/saturnclient/modules/mods/Keystrokes.java index 5cdef8f..f3358da 100644 --- a/src/main/java/org/saturnclient/modules/mods/Keystrokes.java +++ b/src/main/java/org/saturnclient/modules/mods/Keystrokes.java @@ -110,13 +110,13 @@ public class Keystrokes extends Module implements HudMod { renderKey(scope, s, 'S', 27, 27); // Bottom center renderKey(scope, d, 'D', 54, 27); // Bottom right - if (showMouse.value) { - renderKeyM(scope, lmb, "LMB", 0, 54); // Below A/S/D - renderKeyM(scope, rmb, "RMB", 40, 54); // With 3px between + if (showSpace.value) { + renderKeySpace(scope, space, 0, 37); } - if (showSpace.value) { - renderKeySpace(scope, space, 0, cachedHeight - (showSpace.value ? 22 : 0)); + if (showMouse.value) { + renderKeyM(scope, lmb, "LMB", 0, showSpace.value ? 73 : 54); // Below A/S/D + renderKeyM(scope, rmb, "RMB", 40, showSpace.value ? 73 : 54); // With 3px between } } From f9c0d3fe58f277aea884f64020e8ae23622d28e2 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 23 Feb 2026 00:24:14 +0100 Subject: [PATCH 08/18] Fixed keystrokes --- .../saturnclient/modules/mods/Keystrokes.java | 159 ++++++++---------- 1 file changed, 69 insertions(+), 90 deletions(-) diff --git a/src/main/java/org/saturnclient/modules/mods/Keystrokes.java b/src/main/java/org/saturnclient/modules/mods/Keystrokes.java index f3358da..7b356ea 100644 --- a/src/main/java/org/saturnclient/modules/mods/Keystrokes.java +++ b/src/main/java/org/saturnclient/modules/mods/Keystrokes.java @@ -9,46 +9,45 @@ import org.saturnclient.ui2.RenderScope; import org.saturnclient.modules.ModuleDetails; public class Keystrokes extends Module implements HudMod { - public static Property enabled = Property.bool(false); - public static Property showMouse = Property.bool(true); - public static Property showSpace = Property.bool(false); - public static ModDimensions dimensions = new ModDimensions(78, 46); - // Cache key states to avoid repeated calls - private boolean w = false; - private boolean a = false; - private boolean s = false; - private boolean d = false; - private boolean lmb = false; - private boolean rmb = false; - private boolean space = false; + private static final Property enabled = Property.bool(false); + private static final Property showMouse = Property.bool(true); + private static final Property showSpace = Property.bool(false); - // Cache dimensions to avoid recalculation - private int cachedHeight = 54; - private boolean dimensionsDirty = true; + private static final Property clickBg = Property.color(0xFFCCCCCC); + private static final Property clickFg = Property.color(0xFFFFFFFF); - private static Property clickBg = Property.color(0xFFCCCCCC); - private static Property clickFg = Property.color(0xFFFFFFFF); + private static final ModDimensions dimensions = new ModDimensions(78, 54); + + // Key states + private boolean w, a, s, d, lmb, rmb, space; + + // Layout constants + private static final int KEY_SIZE = 24; + private static final int KEY_SPACING = 3; + private static final int MOUSE_WIDTH = 38; + private static final int MOUSE_HEIGHT = 24; + private static final int SPACE_HEIGHT = 19; public Keystrokes() { super(new ModuleDetails("Keystrokes", "keystrokes") - .description("Displays the keystrokes for movement") - .version("v0.1.0") + .description("Displays movement keystrokes") + .version("v0.2.0") .tags("Utility"), enabled.named("Enabled"), showMouse.named("Show mouse clicks"), - showSpace.named("Show space clicks"), + showSpace.named("Show space"), dimensions.prop(), clickFg.named("Clicked fg"), - clickBg.named("Clicked bg")); + clickBg.named("Clicked bg") + ); dimensions.renderBackground = false; } @Override public void tick() { - // Cache key states to reduce method calls w = SaturnClient.client.options.forwardKey.isPressed(); a = SaturnClient.client.options.leftKey.isPressed(); s = SaturnClient.client.options.backKey.isPressed(); @@ -57,103 +56,84 @@ public class Keystrokes extends Module implements HudMod { rmb = SaturnClient.client.options.useKey.isPressed(); space = SaturnClient.client.options.jumpKey.isPressed(); - // Mark dimensions as dirty if mouse or space visibility changed - if (dimensionsDirty) { - updateDimensions(); - dimensionsDirty = false; - } + updateHeight(); } - private void updateDimensions() { - cachedHeight = 54; // base height with padding considered + private void updateHeight() { + int height = KEY_SIZE * 2 + KEY_SPACING; - if (showMouse.value) { - cachedHeight += 27; - } + if (showSpace.value) + height += SPACE_HEIGHT + KEY_SPACING; - if (showSpace.value) { - cachedHeight += 22; - } + if (showMouse.value) + height += MOUSE_HEIGHT + KEY_SPACING; - dimensions.height = cachedHeight; + dimensions.height = height; } @Override public void renderDummy(RenderScope scope) { - // Use cached dimensions - dimensions.height = cachedHeight; - - // WASD keys (3px padding between each key) - renderKey(scope, false, 'W', 27, 0); // Top center - renderKey(scope, false, 'A', 0, 27); // Bottom left - renderKey(scope, false, 'S', 27, 27); // Bottom center - renderKey(scope, false, 'D', 54, 27); // Bottom right - - if (showMouse.value) { - renderKeyM(scope, false, "LMB", 0, 54); // Below A/S/D - renderKeyM(scope, false, "RMB", 40, 54); // With 3px between - } - - if (showSpace.value) { - renderKeySpace(scope, false, 0, cachedHeight - (showSpace.value ? 22 : 0)); - } + render(scope, false); } @Override public void renderHud(RenderScope scope) { - // Use cached dimensions - dimensions.height = cachedHeight; + render(scope, true); + } - // WASD keys (3px padding between each key) - renderKey(scope, w, 'W', 27, 0); // Top center - renderKey(scope, a, 'A', 0, 27); // Bottom left - renderKey(scope, s, 'S', 27, 27); // Bottom center - renderKey(scope, d, 'D', 54, 27); // Bottom right + private void render(RenderScope scope, boolean live) { + int yOffset = 0; + + // --- W --- + renderKey(scope, live && w, 'W', KEY_SIZE + KEY_SPACING, yOffset); + + // --- A S D --- + yOffset += KEY_SIZE + KEY_SPACING; + + renderKey(scope, live && a, 'A', 0, yOffset); + renderKey(scope, live && s, 'S', KEY_SIZE + KEY_SPACING, yOffset); + renderKey(scope, live && d, 'D', (KEY_SIZE + KEY_SPACING) * 2, yOffset); + + yOffset += KEY_SIZE + KEY_SPACING; + + // --- SPACE --- if (showSpace.value) { - renderKeySpace(scope, space, 0, 37); + renderKeySpace(scope, live && space, 0, yOffset); + yOffset += SPACE_HEIGHT + KEY_SPACING; } + // --- MOUSE --- if (showMouse.value) { - renderKeyM(scope, lmb, "LMB", 0, showSpace.value ? 73 : 54); // Below A/S/D - renderKeyM(scope, rmb, "RMB", 40, showSpace.value ? 73 : 54); // With 3px between + renderKeyMouse(scope, live && lmb, "LMB", 0, yOffset); + renderKeyMouse(scope, live && rmb, "RMB", MOUSE_WIDTH + KEY_SPACING, yOffset); } } - // Consistent 3px padding applied below: + private void renderKey(RenderScope scope, boolean pressed, char c, int x, int y) { + int bg = pressed ? clickBg.value : dimensions.bgColor.value; + int fg = pressed ? clickFg.value : dimensions.fgColor.value; - private void renderKeySpace(RenderScope scope, boolean isPressed, int x, int y) { - int height = 19; - int bgColor = isPressed ? clickBg.value : dimensions.bgColor.value; - int fgColor = isPressed ? clickFg.value : dimensions.fgColor.value; - - scope.drawRoundedRectangle(x, y, dimensions.width, height, dimensions.radius.value, bgColor); - - // A 30-pixel line centered vertically with 3px top padding - int lineY = y + (height - 1) / 2; - scope.drawRect(x + (dimensions.width - 30) / 2, lineY, 30, 1, fgColor); + scope.drawRoundedRectangle(x, y, KEY_SIZE, KEY_SIZE, dimensions.radius.value, bg); + scope.drawText(0.6f, String.valueOf(c), x + 9, y + 7, dimensions.font.value, fg); } - private void renderKeyM(RenderScope scope, boolean isPressed, String c, int x, int y) { - int width = 38, height = 24; - int bgColor = isPressed ? clickBg.value : dimensions.bgColor.value; - int fgColor = isPressed ? clickFg.value : dimensions.fgColor.value; + private void renderKeyMouse(RenderScope scope, boolean pressed, String text, int x, int y) { + int bg = pressed ? clickBg.value : dimensions.bgColor.value; + int fg = pressed ? clickFg.value : dimensions.fgColor.value; - scope.drawRoundedRectangle(x, y, width, height, dimensions.radius.value, bgColor); - - // Apply padding: 3px top and left -> add slight offset to x/y - scope.drawText(0.6f, c, x + 9, y + 7, dimensions.font.value, fgColor); + scope.drawRoundedRectangle(x, y, MOUSE_WIDTH, MOUSE_HEIGHT, dimensions.radius.value, bg); + scope.drawText(0.6f, text, x + 9, y + 7, dimensions.font.value, fg); } - private void renderKey(RenderScope scope, boolean isPressed, char c, int x, int y) { - int size = 24; - int bgColor = isPressed ? clickBg.value : dimensions.bgColor.value; - int fgColor = isPressed ? clickFg.value : dimensions.fgColor.value; + private void renderKeySpace(RenderScope scope, boolean pressed, int x, int y) { + int bg = pressed ? clickBg.value : dimensions.bgColor.value; + int fg = pressed ? clickFg.value : dimensions.fgColor.value; - scope.drawRoundedRectangle(x, y, size, size, dimensions.radius.value, bgColor); + scope.drawRoundedRectangle(x, y, dimensions.width, SPACE_HEIGHT, dimensions.radius.value, bg); - // Center the character with 3px top padding - scope.drawText(0.6f, String.valueOf(c), x + 9, y + 7, dimensions.font.value, fgColor); + int lineY = y + SPACE_HEIGHT / 2; + scope.drawRect(x + (dimensions.width - 30) / 2, lineY, 30, 1, fg); } @Override @@ -169,6 +149,5 @@ public class Keystrokes extends Module implements HudMod { @Override public void onEnabled(boolean e) { enabled.value = e; - dimensionsDirty = true; } } \ No newline at end of file From c5c38247ccce101a6319d708c3c3e5c43c2a84b3 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 23 Feb 2026 03:45:26 +0100 Subject: [PATCH 09/18] Improved build.gradle --- build.gradle | 186 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 144 insertions(+), 42 deletions(-) diff --git a/build.gradle b/build.gradle index 1266b7f..2384564 100644 --- a/build.gradle +++ b/build.gradle @@ -1,46 +1,126 @@ +/* + * ================================================================ + * Saturn Client - Fabric Mod Build Configuration + * ================================================================ + * + * This build file configures: + * - Fabric Loom (Minecraft mod development) + * - Dependency management + * - Resource processing + * - Java toolchain (Java 21) + * - Publishing setup + * + * All version values are defined in gradle.properties. + * ================================================================ + */ + plugins { + // Fabric mod development plugin id 'fabric-loom' version '1.9-SNAPSHOT' + + // Maven publishing support id 'maven-publish' } +/* + * ================================================================ + * Project Metadata + * ================================================================ + */ + version = project.mod_version -group = project.maven_group - -repositories {} - -dependencies { - minecraft "com.mojang:minecraft:${project.minecraft_version}" - - // Switch back to Yarn - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - - modApi "dev.felnull:special-model-loader:1.4.0+pre.1" - include "dev.felnull:special-model-loader:1.4.0+pre.1" - - implementation 'com.github.selimaj-dev:session-java:0.1.4' - - // implementation("com.kitfox.svg:svg-salamander:1.1.3") - implementation 'com.formdev:svgSalamander:1.1.4' - - include modImplementation("dev.kosmx.player-anim:player-animation-lib-fabric:${project.player_anim}") - //You might want bendy-lib. playerAnimator will wrap it. - // include modRuntimeOnly("io.github.kosmx.bendy-lib:bendy-lib-fabric:${project.bendylib_version}") -} - +group = project.maven_group +/* + * ================================================================ + * Repositories + * ================================================================ + * All dependency sources. + */ repositories { + // Fabric maven { url 'https://maven.fabricmc.net/' } - maven { url 'https://jitpack.io' } - maven { url "https://maven.parchmentmc.org" } - maven { name = "FelNull Maven"; url = "https://maven.felnull.dev" } - maven { name = "KosmX maven"; url = 'https://maven.kosmx.dev/' } + // JitPack (GitHub releases) + maven { url 'https://jitpack.io' } + + // Parchment mappings (if needed later) + maven { url 'https://maven.parchmentmc.org' } + + // Special Model Loader + maven { name = "FelNull Maven"; url = "https://maven.felnull.dev" } + + // Player Animation Library + maven { name = "KosmX Maven"; url = 'https://maven.kosmx.dev/' } + + // Central repository mavenCentral() } +/* + * ================================================================ + * Dependencies + * ================================================================ + */ +dependencies { + + // ───────────────────────────────────────────── + // Minecraft Core + // ───────────────────────────────────────────── + minecraft "com.mojang:minecraft:${project.minecraft_version}" + + // Yarn mappings (named mappings for dev environment) + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + + // Fabric Loader + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + + // ───────────────────────────────────────────── + // Rendering / Model Libraries + // ───────────────────────────────────────────── + + // Special Model Loader (included inside your mod jar) + modApi "dev.felnull:special-model-loader:1.4.0+pre.1" + include "dev.felnull:special-model-loader:1.4.0+pre.1" + + // SVG Rendering Library + implementation "com.formdev:svgSalamander:1.1.4" + + + // ───────────────────────────────────────────── + // Animation + // ───────────────────────────────────────────── + + // Player Animation Library (bundled into your mod) + include modImplementation( + "dev.kosmx.player-anim:player-animation-lib-fabric:${project.player_anim}" + ) + + // Optional: BendyLib (only if you directly use it) + // include modRuntimeOnly( + // "io.github.kosmx.bendy-lib:bendy-lib-fabric:${project.bendylib_version}" + // ) + + + // ───────────────────────────────────────────── + // External Libraries + // ───────────────────────────────────────────── + + // Session Java (auth/session handling) + implementation "com.github.selimaj-dev:session-java:0.1.4" +} + + +/* + * ================================================================ + * Resource Processing + * ================================================================ + * Injects version values into fabric.mod.json. + */ processResources { inputs.property "version", project.version inputs.property "minecraft_version", project.minecraft_version @@ -48,38 +128,58 @@ processResources { filteringCharset "UTF-8" filesMatching("fabric.mod.json") { - expand "version": project.version, + expand( + "version": project.version, "minecraft_version": project.minecraft_version, "loader_version": project.loader_version + ) } } + +/* + * ================================================================ + * Java Configuration + * ================================================================ + * Targeting Java 21. + */ def targetJavaVersion = 21 + tasks.withType(JavaCompile).configureEach { - it.options.encoding = "UTF-8" - if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { - it.options.release.set(targetJavaVersion) - } + options.encoding = "UTF-8" + options.release.set(targetJavaVersion) } java { - def javaVersion = JavaVersion.toVersion(targetJavaVersion) - if (JavaVersion.current() < javaVersion) { - toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) - } + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + archivesBaseName = project.archives_base_name withSourcesJar() } + +/* + * ================================================================ + * Jar Packaging + * ================================================================ + * Includes LICENSE and NOTICE inside the final jar. + */ jar { from("LICENSE") { - rename { "${it}_${project.archivesBaseName}"} + rename { "${it}_${project.archivesBaseName}" } } from("NOTICE") { - rename { "${it}_${project.archivesBaseName}"} + rename { "${it}_${project.archivesBaseName}" } } } + +/* + * ================================================================ + * Publishing + * ================================================================ + * Configured but no remote repository defined yet. + */ publishing { publications { mavenJava(MavenPublication) { @@ -87,5 +187,7 @@ publishing { } } - repositories {} + repositories { + // Add publishing repository here when needed + } } \ No newline at end of file From 8614e1bdd1176b8c52fd8eb8ae33a0809c44dc2d Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 23 Feb 2026 06:47:08 +0100 Subject: [PATCH 10/18] Working service system --- build.gradle | 2 +- .../saturnclient/client/ServiceClient.java | 36 +++++++++++++++---- .../ui2/resources/SvgTexture.java | 1 - 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 2384564..8d5fc02 100644 --- a/build.gradle +++ b/build.gradle @@ -111,7 +111,7 @@ dependencies { // ───────────────────────────────────────────── // Session Java (auth/session handling) - implementation "com.github.selimaj-dev:session-java:0.1.4" + implementation "com.github.selimaj-dev:session-java:0.1.5" } diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index 8876664..4a9f364 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -46,7 +46,7 @@ public class ServiceClient { uuid = mcSession.getUuidOrNull(); String username = mcSession.getUsername(); - SaturnClient.LOGGER.info("Authenticating with UUID: " + accessToken); + SaturnClient.LOGGER.info("Authenticating with UUID: " + uuid); if (!connectTimeout()) { SaturnClient.LOGGER.error("Unable to authenticate: Session Server Timeout"); @@ -76,7 +76,11 @@ public class ServiceClient { public static void setCloak(String cloak) { try { - session.request(ServiceMethods.SetCloak, cloak).get(); + session.request(ServiceMethods.SetCloak, cloak).whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } + }); } catch (Exception e) { SaturnClient.LOGGER.error("Failed to set cloak (service): ", e); } @@ -84,7 +88,11 @@ public class ServiceClient { public static void setHat(String hat) { try { - session.request(ServiceMethods.SetHat, hat).get(); + session.request(ServiceMethods.SetHat, hat).whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } + }); } catch (Exception e) { SaturnClient.LOGGER.error("Failed to set hat (service): ", e); } @@ -92,7 +100,13 @@ public class ServiceClient { public static void buyCloak(String cloak) { try { - session.request(ServiceMethods.BuyCloak, cloak).get(); + session.request(ServiceMethods.BuyCloak, cloak).whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + Cloaks.availableCloaks.add(cloak); + } + }); } catch (Exception e) { SaturnClient.LOGGER.error("Failed to buy cloak (service): ", e); } @@ -100,7 +114,13 @@ public class ServiceClient { public static void buyHat(String hat) { try { - session.request(ServiceMethods.BuyHat, hat).get(); + session.request(ServiceMethods.BuyHat, hat).whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + Hats.availableHats.add(hat); + } + }); } catch (Exception e) { SaturnClient.LOGGER.error("Failed to buy hat (service): ", e); } @@ -108,7 +128,11 @@ public class ServiceClient { public static void emote(String emote) { try { - session.request(ServiceMethods.Emote, emote).get(); + session.request(ServiceMethods.Emote, emote).whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } + }); } catch (Exception e) { SaturnClient.LOGGER.error("Failed to emote (service): ", e); } diff --git a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java index 937a79e..0bcd0f8 100644 --- a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java +++ b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java @@ -53,7 +53,6 @@ public class SvgTexture { } @Nullable - @SuppressWarnings("resource") public static Identifier getSvg(MinecraftClient client, Identifier svgImage, int width, int height) { Identifier id = Identifier .of(svgImage.toString().replaceAll("\\.svg$", (width + "_" + height).toString() + ".png")); From df35497af29fefa0b77d66984d9e430a0dafa3e8 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 23 Feb 2026 07:18:54 +0100 Subject: [PATCH 11/18] Trying to find the hat rendering issue --- .../saturnclient/client/ServiceClient.java | 20 +++++++++---------- .../cosmetics/HatFeatureRenderer.java | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index 4a9f364..a6bccaf 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -74,9 +74,9 @@ public class ServiceClient { } } - public static void setCloak(String cloak) { + public static void setCloak(String itemId) { try { - session.request(ServiceMethods.SetCloak, cloak).whenComplete((msg, throwable) -> { + session.request(ServiceMethods.SetCloak, itemId).whenComplete((msg, throwable) -> { if (throwable != null) { throwable.printStackTrace(); } @@ -86,9 +86,9 @@ public class ServiceClient { } } - public static void setHat(String hat) { + public static void setHat(String itemId) { try { - session.request(ServiceMethods.SetHat, hat).whenComplete((msg, throwable) -> { + session.request(ServiceMethods.SetHat, itemId).whenComplete((msg, throwable) -> { if (throwable != null) { throwable.printStackTrace(); } @@ -98,13 +98,13 @@ public class ServiceClient { } } - public static void buyCloak(String cloak) { + public static void buyCloak(String itemId) { try { - session.request(ServiceMethods.BuyCloak, cloak).whenComplete((msg, throwable) -> { + session.request(ServiceMethods.BuyCloak, itemId).whenComplete((msg, throwable) -> { if (throwable != null) { throwable.printStackTrace(); } else { - Cloaks.availableCloaks.add(cloak); + Cloaks.availableCloaks.add(itemId); } }); } catch (Exception e) { @@ -112,13 +112,13 @@ public class ServiceClient { } } - public static void buyHat(String hat) { + public static void buyHat(String itemId) { try { - session.request(ServiceMethods.BuyHat, hat).whenComplete((msg, throwable) -> { + session.request(ServiceMethods.BuyHat, itemId).whenComplete((msg, throwable) -> { if (throwable != null) { throwable.printStackTrace(); } else { - Hats.availableHats.add(hat); + Hats.availableHats.add(itemId); } }); } catch (Exception e) { diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java index 2f7e061..4d741d1 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java @@ -28,6 +28,7 @@ public class HatFeatureRenderer extends FeatureRenderer Date: Mon, 23 Feb 2026 07:22:44 +0100 Subject: [PATCH 12/18] Fixed the hat rendering issue --- .../saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java index 4d741d1..158c29a 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java @@ -29,7 +29,7 @@ public class HatFeatureRenderer extends FeatureRenderer Date: Mon, 23 Feb 2026 09:20:10 +0100 Subject: [PATCH 13/18] Fixing emote system --- .../saturnclient/client/ServiceClient.java | 51 ++++++++++++++++--- .../saturnclient/client/ServiceMethods.java | 21 ++++++-- .../cosmetics/HatFeatureRenderer.java | 2 +- src/main/java/org/saturnclient/ui2/Utils.java | 1 - .../saturnclient/ui2/screens/EmoteWheel.java | 14 ++--- 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index a6bccaf..ea19364 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -1,6 +1,7 @@ package org.saturnclient.saturnclient.client; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import org.saturnclient.saturnclient.SaturnClient; @@ -8,8 +9,14 @@ import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.cosmetics.Hats; import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; +import dev.kosmx.playerAnim.api.layered.AnimationStack; +import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationAccess; +import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationRegistry; import dev.selimaj.session.Session; +import dev.selimaj.session.types.SessionResult; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.util.Identifier; public class ServiceClient { private static Session session; @@ -53,7 +60,8 @@ public class ServiceClient { return false; } - ServiceMethods.AuthResponse response = session.request(ServiceMethods.Authenticate, accessToken).get(); + ServiceMethods.Types.AuthResponse response = session.request(ServiceMethods.Authenticate, accessToken) + .get(); for (String availableCloak : response.cloaks()) { Cloaks.availableCloaks.add(availableCloak); @@ -63,6 +71,8 @@ public class ServiceClient { Hats.availableHats.add(availableHat); } + eventHandlers(); + SaturnPlayer.set(uuid, username, new SaturnPlayer(uuid, username, response.cloak(), response.hat())); Cloaks.loadCloak(uuid); @@ -128,13 +138,42 @@ public class ServiceClient { public static void emote(String emote) { try { - session.request(ServiceMethods.Emote, emote).whenComplete((msg, throwable) -> { - if (throwable != null) { - throwable.printStackTrace(); - } - }); + String[] targets = { uuid.toString().replaceAll("-", "") }; + + session.request(ServiceMethods.Emote, + new ServiceMethods.Types.EmoteRequest(emote, targets)) + .whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } + }); } catch (Exception e) { SaturnClient.LOGGER.error("Failed to emote (service): ", e); } } + + public static void eventHandlers() { + session.onNotification(ServiceMethods.EmoteEvent, (l, data) -> { + return CompletableFuture.supplyAsync(() -> { + for (AbstractClientPlayerEntity player : SaturnClient.client.world.getPlayers()) { + if (player.getUuidAsString().replace("-", "").equals(data.from())) { + AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(player); + if (data.emote() != null && !data.emote().isEmpty()) { + if (animationStack.isActive() && animationStack.getPriority() == 1000) { + animationStack.removeLayer(1000); + } + animationStack.addAnimLayer(1000, + PlayerAnimationRegistry + .getAnimation(Identifier.of("saturnclient", data.emote())) + .playAnimation()); + } else { + animationStack.removeLayer(1000); + } + } + } + + return SessionResult.ok(""); + }); + }); + } } diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java index 7eb9dea..afb0ccf 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java @@ -3,11 +3,19 @@ package org.saturnclient.saturnclient.client; import dev.selimaj.session.types.Method; public class ServiceMethods { - public record AuthResponse(String cloak, String hat, String[] cloaks, String[] hats) { + public class Types { + public record AuthResponse(String cloak, String hat, String[] cloaks, String[] hats) { + } + + public record EmoteRequest(String emote, String[] targets) { + } + + public record EmoteEvent(String emote, String from) { + } } - public static final Method Authenticate = new Method<>("auth", - String.class, AuthResponse.class, String.class); + public static final Method Authenticate = new Method<>("auth", + String.class, Types.AuthResponse.class, String.class); // Equip public static final Method SetCloak = new Method<>("set_cloak", @@ -22,6 +30,9 @@ public class ServiceMethods { String.class, String.class, String.class); // Emote - public static final Method Emote = new Method<>("emote", - String.class, String.class, String.class); + public static final Method Emote = new Method<>("emote", + Types.EmoteRequest.class, String.class, String.class); + + public static final Method EmoteEvent = new Method<>("emote_event", + Types.EmoteEvent.class, String.class, String.class); } \ No newline at end of file diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java index 158c29a..cabc440 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java @@ -28,7 +28,7 @@ public class HatFeatureRenderer extends FeatureRenderer T getOrNull(List list, int index) { - SaturnClient.LOGGER.info("Accessing index {} in list of size {}", index, list.size()); return (index >= 0 && index < list.size()) ? list.get(index) : null; } diff --git a/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java b/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java index 55d6fe1..ab726ea 100644 --- a/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java +++ b/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java @@ -63,13 +63,13 @@ public class EmoteWheel extends SaturnScreen { if (emote == null) { return; } - AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(SaturnClient.client.player); - if (animationStack.isActive() && animationStack.getPriority() == 1000) { - animationStack.removeLayer(1000); - } - animationStack.addAnimLayer(1000, - PlayerAnimationRegistry.getAnimation(Identifier.of("saturnclient", - emote)).playAnimation()); + // AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(SaturnClient.client.player); + // if (animationStack.isActive() && animationStack.getPriority() == 1000) { + // animationStack.removeLayer(1000); + // } + // animationStack.addAnimLayer(1000, + // PlayerAnimationRegistry.getAnimation(Identifier.of("saturnclient", + // emote)).playAnimation()); ServiceClient.emote(emote); close(); }).dimensions(70, 70).centerOffset(width, height, -80 + (col * 80), -35 + (row * 80)) From 2a425335f06a1bea139349915909b0190c7bd4b4 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 23 Feb 2026 09:34:38 +0100 Subject: [PATCH 14/18] Working emote streaming --- build.gradle | 2 +- .../saturnclient/client/ServiceClient.java | 36 ++++++++----------- .../client/player/SaturnPlayer.java | 6 ++++ .../saturnclient/ui2/screens/EmoteWheel.java | 14 ++++---- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/build.gradle b/build.gradle index 8d5fc02..0d0efed 100644 --- a/build.gradle +++ b/build.gradle @@ -111,7 +111,7 @@ dependencies { // ───────────────────────────────────────────── // Session Java (auth/session handling) - implementation "com.github.selimaj-dev:session-java:0.1.5" + implementation "com.github.selimaj-dev:session-java:0.1.6" } diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index ea19364..615b3b2 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -1,7 +1,6 @@ package org.saturnclient.saturnclient.client; import java.util.UUID; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import org.saturnclient.saturnclient.SaturnClient; @@ -13,7 +12,6 @@ import dev.kosmx.playerAnim.api.layered.AnimationStack; import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationAccess; import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationRegistry; import dev.selimaj.session.Session; -import dev.selimaj.session.types.SessionResult; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.util.Identifier; @@ -138,10 +136,8 @@ public class ServiceClient { public static void emote(String emote) { try { - String[] targets = { uuid.toString().replaceAll("-", "") }; - session.request(ServiceMethods.Emote, - new ServiceMethods.Types.EmoteRequest(emote, targets)) + new ServiceMethods.Types.EmoteRequest(emote, SaturnPlayer.getExternalUUIDAsString())) .whenComplete((msg, throwable) -> { if (throwable != null) { throwable.printStackTrace(); @@ -153,27 +149,23 @@ public class ServiceClient { } public static void eventHandlers() { - session.onNotification(ServiceMethods.EmoteEvent, (l, data) -> { - return CompletableFuture.supplyAsync(() -> { - for (AbstractClientPlayerEntity player : SaturnClient.client.world.getPlayers()) { - if (player.getUuidAsString().replace("-", "").equals(data.from())) { - AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(player); - if (data.emote() != null && !data.emote().isEmpty()) { - if (animationStack.isActive() && animationStack.getPriority() == 1000) { - animationStack.removeLayer(1000); - } - animationStack.addAnimLayer(1000, - PlayerAnimationRegistry - .getAnimation(Identifier.of("saturnclient", data.emote())) - .playAnimation()); - } else { + session.onNotification(ServiceMethods.EmoteEvent, (data) -> { + for (AbstractClientPlayerEntity player : SaturnClient.client.world.getPlayers()) { + if (player.getUuidAsString().replace("-", "").equals(data.from())) { + AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(player); + if (data.emote() != null && !data.emote().isEmpty()) { + if (animationStack.isActive() && animationStack.getPriority() == 1000) { animationStack.removeLayer(1000); } + animationStack.addAnimLayer(1000, + PlayerAnimationRegistry + .getAnimation(Identifier.of("saturnclient", data.emote())) + .playAnimation()); + } else { + animationStack.removeLayer(1000); } } - - return SessionResult.ok(""); - }); + } }); } } diff --git a/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java index a6caf95..edcd633 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java +++ b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java @@ -55,4 +55,10 @@ public class SaturnPlayer { PLAYERS.put(uuid, null); } + + public static String[] getExternalUUIDAsString() { + return PLAYERS.keySet().stream().filter(id -> !id.equals(ServiceClient.uuid)).map(UUID::toString) + .toArray(String[]::new); + } + } diff --git a/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java b/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java index ab726ea..55d6fe1 100644 --- a/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java +++ b/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java @@ -63,13 +63,13 @@ public class EmoteWheel extends SaturnScreen { if (emote == null) { return; } - // AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(SaturnClient.client.player); - // if (animationStack.isActive() && animationStack.getPriority() == 1000) { - // animationStack.removeLayer(1000); - // } - // animationStack.addAnimLayer(1000, - // PlayerAnimationRegistry.getAnimation(Identifier.of("saturnclient", - // emote)).playAnimation()); + AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(SaturnClient.client.player); + if (animationStack.isActive() && animationStack.getPriority() == 1000) { + animationStack.removeLayer(1000); + } + animationStack.addAnimLayer(1000, + PlayerAnimationRegistry.getAnimation(Identifier.of("saturnclient", + emote)).playAnimation()); ServiceClient.emote(emote); close(); }).dimensions(70, 70).centerOffset(width, height, -80 + (col * 80), -35 + (row * 80)) From 68b4bfc439781b42785d9d915a0429f6c6fab1a8 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 23 Feb 2026 16:29:48 +0100 Subject: [PATCH 15/18] Working peer player --- .../saturnclient/client/ServiceClient.java | 19 ++++++++++++++++-- .../saturnclient/client/ServiceMethods.java | 20 ++++++++++++++----- .../client/player/PlayerTracker.java | 4 ++-- .../client/player/SaturnPlayer.java | 16 +++------------ 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index 615b3b2..777f5de 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -58,7 +58,7 @@ public class ServiceClient { return false; } - ServiceMethods.Types.AuthResponse response = session.request(ServiceMethods.Authenticate, accessToken) + ServiceMethods.Types.Player response = session.request(ServiceMethods.Authenticate, accessToken) .get(); for (String availableCloak : response.cloaks()) { @@ -71,7 +71,7 @@ public class ServiceClient { eventHandlers(); - SaturnPlayer.set(uuid, username, new SaturnPlayer(uuid, username, response.cloak(), response.hat())); + player(uuid, username); Cloaks.loadCloak(uuid); @@ -168,4 +168,19 @@ public class ServiceClient { } }); } + + public static void player(UUID uuid, String name) { + try { + session.request(ServiceMethods.Player, uuid.toString().replaceAll("-", "")) + .whenComplete((user, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + SaturnPlayer.set(user.toSaturnPlayer(uuid, name)); + } + }); + } catch (Exception e) { + SaturnClient.LOGGER.error("Failed to get player", e); + } + } } diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java index afb0ccf..1f5d986 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java @@ -1,21 +1,28 @@ package org.saturnclient.saturnclient.client; +import java.util.UUID; + +import org.saturnclient.saturnclient.client.player.SaturnPlayer; + import dev.selimaj.session.types.Method; public class ServiceMethods { public class Types { - public record AuthResponse(String cloak, String hat, String[] cloaks, String[] hats) { - } - public record EmoteRequest(String emote, String[] targets) { } public record EmoteEvent(String emote, String from) { } + + public record Player(String cloak, String hat, String[] cloaks, String[] hats) { + public SaturnPlayer toSaturnPlayer(UUID uuid, String name) { + return new SaturnPlayer(uuid, name, cloak, hat); + } + } } - public static final Method Authenticate = new Method<>("auth", - String.class, Types.AuthResponse.class, String.class); + public static final Method Authenticate = new Method<>("auth", + String.class, Types.Player.class, String.class); // Equip public static final Method SetCloak = new Method<>("set_cloak", @@ -35,4 +42,7 @@ public class ServiceMethods { public static final Method EmoteEvent = new Method<>("emote_event", Types.EmoteEvent.class, String.class, String.class); + + public static final Method Player = new Method<>("player", + String.class, Types.Player.class, String.class); } \ No newline at end of file diff --git a/src/main/java/org/saturnclient/saturnclient/client/player/PlayerTracker.java b/src/main/java/org/saturnclient/saturnclient/client/player/PlayerTracker.java index 2a27c6b..f43347f 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/player/PlayerTracker.java +++ b/src/main/java/org/saturnclient/saturnclient/client/player/PlayerTracker.java @@ -3,6 +3,7 @@ package org.saturnclient.saturnclient.client.player; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.saturnclient.client.ServiceClient; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.MinecraftClient; @@ -46,7 +47,6 @@ public class PlayerTracker { private static void onPlayerJoin(MinecraftClient client, PlayerListEntry player) { GameProfile profile = player.getProfile(); - UUID uuid = profile.getId(); - SaturnPlayer.player(uuid); + ServiceClient.player(profile.getId(), profile.getName()); } } diff --git a/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java index edcd633..f4c935e 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java +++ b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java @@ -41,19 +41,9 @@ public class SaturnPlayer { return PLAYERS.get(uuid); } - public static void set(UUID uuid, String name, SaturnPlayer player) { - PLAYER_NAMES.put(name, uuid); - PLAYERS.put(uuid, player); - } - - public static void player(UUID uuid) { - if (PLAYERS.containsKey(uuid)) { - return; - } - - // If offline then leave - - PLAYERS.put(uuid, null); + public static void set(SaturnPlayer player) { + PLAYER_NAMES.put(player.name, player.uuid); + PLAYERS.put(player.uuid, player); } public static String[] getExternalUUIDAsString() { From bbf4b1749454ca63f5b73e7b7a31a73683cc8cce Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 23 Feb 2026 17:46:28 +0100 Subject: [PATCH 16/18] Attempting to fix sendplayer --- .../saturnclient/client/ServiceClient.java | 23 ++++- .../saturnclient/client/ServiceMethods.java | 97 ++++++++++++++++--- .../client/player/SaturnPlayer.java | 2 +- .../saturnclient/cosmetics/cloaks/Cloaks.java | 2 +- 4 files changed, 104 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index 777f5de..27611bf 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -87,6 +87,13 @@ public class ServiceClient { session.request(ServiceMethods.SetCloak, itemId).whenComplete((msg, throwable) -> { if (throwable != null) { throwable.printStackTrace(); + } else { + try { + session.request(ServiceMethods.SendPlayer, + new ServiceMethods.Types.SendPlayerRequest(SaturnPlayer.getExternalUUIDAsString())); + } catch (Exception e) { + e.printStackTrace(); + } } }); } catch (Exception e) { @@ -99,6 +106,13 @@ public class ServiceClient { session.request(ServiceMethods.SetHat, itemId).whenComplete((msg, throwable) -> { if (throwable != null) { throwable.printStackTrace(); + } else { + try { + session.request(ServiceMethods.SendPlayer, + new ServiceMethods.Types.SendPlayerRequest(SaturnPlayer.getExternalUUIDAsString())); + } catch (Exception e) { + e.printStackTrace(); + } } }); } catch (Exception e) { @@ -167,15 +181,20 @@ public class ServiceClient { } } }); + + session.onNotification(ServiceMethods.Player, (player) -> { + System.out.println(player); + SaturnPlayer.set(player.toSaturnPlayer()); + }); } public static void player(UUID uuid, String name) { try { - session.request(ServiceMethods.Player, uuid.toString().replaceAll("-", "")) + session.request(ServiceMethods.GetPlayer, uuid.toString().replaceAll("-", "")) .whenComplete((user, throwable) -> { if (throwable != null) { throwable.printStackTrace(); - } else { + } else if (user != null) { SaturnPlayer.set(user.toSaturnPlayer(uuid, name)); } }); diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java index 1f5d986..0a09c53 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceMethods.java @@ -2,47 +2,112 @@ package org.saturnclient.saturnclient.client; import java.util.UUID; +import org.saturnclient.saturnclient.client.ServiceMethods.Types.SendPlayerRequest; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import dev.selimaj.session.types.Method; public class ServiceMethods { - public class Types { + + // ========================= + // Types (Rust structs) + // ========================= + public static class Types { + public record EmoteRequest(String emote, String[] targets) { } public record EmoteEvent(String emote, String from) { } - public record Player(String cloak, String hat, String[] cloaks, String[] hats) { + public record Player( + String cloak, + String hat, + String[] cloaks, + String[] hats) { public SaturnPlayer toSaturnPlayer(UUID uuid, String name) { return new SaturnPlayer(uuid, name, cloak, hat); } } + + public record PlayerStream(Player player, String name, String uuid) { + public SaturnPlayer toSaturnPlayer() { + return new SaturnPlayer(UUID.fromString(uuid), name, this.player.cloak, this.player.hat); + } + } + + public record SendPlayerRequest(String[] targets) { + } } + // ========================= + // AUTH + // ========================= public static final Method Authenticate = new Method<>("auth", - String.class, Types.Player.class, String.class); + String.class, + Types.Player.class, + String.class); - // Equip + // ========================= + // EQUIP + // ========================= public static final Method SetCloak = new Method<>("set_cloak", - String.class, String.class, String.class); + String.class, + String.class, + String.class); + public static final Method SetHat = new Method<>("set_hat", - String.class, String.class, String.class); + String.class, + String.class, + String.class); - // Buy + // ========================= + // BUY + // ========================= public static final Method BuyCloak = new Method<>("buy_cloak", - String.class, String.class, String.class); + String.class, + String.class, + String.class); + public static final Method BuyHat = new Method<>("buy_hat", - String.class, String.class, String.class); + String.class, + String.class, + String.class); - // Emote - public static final Method Emote = new Method<>("emote", - Types.EmoteRequest.class, String.class, String.class); + // ========================= + // EMOTE + // ========================= + public static final Method Emote = new Method<>("emote", + Types.EmoteRequest.class, + Void.class, + String.class); - public static final Method EmoteEvent = new Method<>("emote_event", - Types.EmoteEvent.class, String.class, String.class); + public static final Method EmoteEvent = new Method<>("emote_event", + Types.EmoteEvent.class, + Void.class, + Void.class); - public static final Method Player = new Method<>("player", - String.class, Types.Player.class, String.class); + // ========================= + // GET PLAYER + // ========================= + public static final Method GetPlayer = new Method<>("get_player", + String.class, + Types.Player.class, + String.class); + + // ========================= + // PLAYER (Server Notification) + // ========================= + public static final Method Player = new Method<>("player", + Types.PlayerStream.class, + Void.class, + Void.class); + + // ========================= + // SEND PLAYER + // ========================= + public static final Method SendPlayer = new Method<>("send_player", + SendPlayerRequest.class, + Void.class, + String.class); } \ No newline at end of file diff --git a/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java index f4c935e..bda57c7 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java +++ b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java @@ -47,7 +47,7 @@ public class SaturnPlayer { } public static String[] getExternalUUIDAsString() { - return PLAYERS.keySet().stream().filter(id -> !id.equals(ServiceClient.uuid)).map(UUID::toString) + return PLAYERS.keySet().stream().filter(id -> id.equals(ServiceClient.uuid)).map(UUID::toString) .toArray(String[]::new); } diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java index d624942..f8140df 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java @@ -62,7 +62,7 @@ public class Cloaks { */ public static void setCloak(String cloakName) { if (availableCloaks.contains(cloakName)) { - setCloak(ServiceClient.uuid, cloakName); + // setCloak(ServiceClient.uuid, cloakName); ServiceClient.setCloak(cloakName); } } From 6717d7e9015f4eb9f6795fbd0efd507b5d958d04 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 23 Feb 2026 18:51:28 +0100 Subject: [PATCH 17/18] Fixed UUID and cloak --- .../org/saturnclient/saturnclient/client/ServiceClient.java | 6 +++--- .../saturnclient/client/player/SaturnPlayer.java | 2 +- .../saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index 27611bf..fe00d24 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -71,7 +71,7 @@ public class ServiceClient { eventHandlers(); - player(uuid, username); + SaturnPlayer.set(new SaturnPlayer(uuid, username, response.cloak(), response.hat())); Cloaks.loadCloak(uuid); @@ -165,7 +165,7 @@ public class ServiceClient { public static void eventHandlers() { session.onNotification(ServiceMethods.EmoteEvent, (data) -> { for (AbstractClientPlayerEntity player : SaturnClient.client.world.getPlayers()) { - if (player.getUuidAsString().replace("-", "").equals(data.from())) { + if (player.getUuidAsString().equals(data.from())) { AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(player); if (data.emote() != null && !data.emote().isEmpty()) { if (animationStack.isActive() && animationStack.getPriority() == 1000) { @@ -190,7 +190,7 @@ public class ServiceClient { public static void player(UUID uuid, String name) { try { - session.request(ServiceMethods.GetPlayer, uuid.toString().replaceAll("-", "")) + session.request(ServiceMethods.GetPlayer, uuid.toString()) .whenComplete((user, throwable) -> { if (throwable != null) { throwable.printStackTrace(); diff --git a/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java index bda57c7..f4c935e 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java +++ b/src/main/java/org/saturnclient/saturnclient/client/player/SaturnPlayer.java @@ -47,7 +47,7 @@ public class SaturnPlayer { } public static String[] getExternalUUIDAsString() { - return PLAYERS.keySet().stream().filter(id -> id.equals(ServiceClient.uuid)).map(UUID::toString) + return PLAYERS.keySet().stream().filter(id -> !id.equals(ServiceClient.uuid)).map(UUID::toString) .toArray(String[]::new); } diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java index f8140df..d624942 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java @@ -62,7 +62,7 @@ public class Cloaks { */ public static void setCloak(String cloakName) { if (availableCloaks.contains(cloakName)) { - // setCloak(ServiceClient.uuid, cloakName); + setCloak(ServiceClient.uuid, cloakName); ServiceClient.setCloak(cloakName); } } From bff18a05d1efd7ae51467392aecde1e1df73d6bb Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 23 Feb 2026 21:30:50 +0100 Subject: [PATCH 18/18] Changed ip to the actual server --- .../org/saturnclient/saturnclient/client/ServiceClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index fe00d24..442f7d9 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -22,7 +22,7 @@ public class ServiceClient { public static boolean connectTimeout() { try { - session = Session.connect("ws://127.0.0.1:8080", 10, TimeUnit.SECONDS); + session = Session.connect("wss://saturn-server.selimaj.dev", 10, TimeUnit.SECONDS); return true; } catch (Exception e) { return false;