From 96d7f5065c35cd69c17afacf19dd535831673561 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 1 Mar 2026 22:17:16 +0100 Subject: [PATCH 01/19] Fixed small waves --- .../saturnclient/cosmetics/CloakFeatureRenderer.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java index 6a519d5..3668e48 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java @@ -308,8 +308,11 @@ public class CloakFeatureRenderer extends FeatureRenderer= 20) { - float value = Math.min(1.0f, playerEntityRenderState.field_53537 / 108.0f) - + (Math.max(0, playerEntityRenderState.field_53536) / 16); + float velX = Math.min(1.0f, playerEntityRenderState.field_53537 / 108.0f); + float velY = (Math.max(4.0f, playerEntityRenderState.field_53536) - 4.0f) / 16; + + float value = velX + velY; + if (Config.cloakPhysics.value) { updateSegmentValues(value); } else { From 3a922418ca27c724debfed34dbcdad5b38163a18 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 2 Mar 2026 02:00:30 +0100 Subject: [PATCH 02/19] Fixed pivot --- .../cosmetics/CloakFeatureRenderer.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java index 3668e48..e90775f 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java @@ -208,23 +208,23 @@ public class CloakFeatureRenderer extends FeatureRenderer Date: Mon, 2 Mar 2026 02:11:38 +0100 Subject: [PATCH 03/19] Improved cloak y velocity handling --- .../saturnclient/cosmetics/CloakFeatureRenderer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java index e90775f..c9b52ab 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java @@ -35,7 +35,7 @@ import net.minecraft.util.math.Vec3d; */ public class CloakFeatureRenderer extends FeatureRenderer { private final EquipmentModelLoader equipmentModelLoader; - private static final int PARTS = 16; + private static final int PARTS = 24; private final float[] segmentValues = new float[PARTS]; private static final float TEX_W = 176f; @@ -309,7 +309,8 @@ public class CloakFeatureRenderer extends FeatureRenderer= 20) { float velX = Math.min(1.0f, playerEntityRenderState.field_53537 / 108.0f); - float velY = (Math.max(4.0f, playerEntityRenderState.field_53536) - 4.0f) / 16; + float rawVelY = playerEntityRenderState.field_53536; + float velY = (rawVelY > 4.0f ? rawVelY : 0.0f) / 16; float value = velX + velY; From a497d2a14fd79eb3b5df9f221fd478434ea43b40 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 2 Mar 2026 02:50:28 +0100 Subject: [PATCH 04/19] Cloak sneak and swim handling --- .../saturnclient/cosmetics/CloakFeatureRenderer.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java index c9b52ab..68280cb 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java @@ -24,6 +24,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.equipment.EquipmentAsset; import net.minecraft.registry.RegistryKey; import net.minecraft.util.Identifier; +import net.minecraft.util.math.RotationAxis; import net.minecraft.util.math.Vec3d; /** @@ -306,13 +307,18 @@ public class CloakFeatureRenderer extends FeatureRenderer= 20) { float velX = Math.min(1.0f, playerEntityRenderState.field_53537 / 108.0f); float rawVelY = playerEntityRenderState.field_53536; float velY = (rawVelY > 4.0f ? rawVelY : 0.0f) / 16; - float value = velX + velY; + float value = playerEntityRenderState.isSwimming ? 0.0f : velX + velY; if (Config.cloakPhysics.value) { updateSegmentValues(value); From 154fbd774f879c20b115b417228ee68c3a0562ae Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 2 Mar 2026 02:56:17 +0100 Subject: [PATCH 05/19] Cosmetics refactor to main --- .../{saturnclient => }/cosmetics/CloakFeatureRenderer.java | 4 ++-- .../saturnclient/{saturnclient => }/cosmetics/Emotes.java | 2 +- .../{saturnclient => }/cosmetics/HatFeatureRenderer.java | 2 +- .../org/saturnclient/{saturnclient => }/cosmetics/Hats.java | 2 +- .../{saturnclient => }/cosmetics/cloaks/Cloaks.java | 6 +++--- .../{saturnclient => }/cosmetics/cloaks/GifDecoder.java | 2 +- .../cosmetics/cloaks/utils/AnimatedCloakData.java | 2 +- .../cosmetics/cloaks/utils/IdentifierUtils.java | 2 +- .../cosmetics/cloaks/utils/RandomUtils.java | 2 +- .../java/org/saturnclient/saturnclient/SaturnClient.java | 6 +++--- .../org/saturnclient/saturnclient/client/ServiceClient.java | 4 ++-- .../saturnclient/mixin/PlayerEntityRendererMixin.java | 4 ++-- .../java/org/saturnclient/ui2/resources/SvgTexture.java | 2 +- src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java | 2 +- .../org/saturnclient/ui2/screens/cosmetics/CloakMenu.java | 2 +- .../org/saturnclient/ui2/screens/cosmetics/HatMenu.java | 2 +- .../java/org/saturnclient/ui2/screens/store/CloakStore.java | 2 +- .../java/org/saturnclient/ui2/screens/store/HatStore.java | 2 +- 18 files changed, 25 insertions(+), 25 deletions(-) rename src/main/java/org/saturnclient/{saturnclient => }/cosmetics/CloakFeatureRenderer.java (99%) rename src/main/java/org/saturnclient/{saturnclient => }/cosmetics/Emotes.java (89%) rename src/main/java/org/saturnclient/{saturnclient => }/cosmetics/HatFeatureRenderer.java (98%) rename src/main/java/org/saturnclient/{saturnclient => }/cosmetics/Hats.java (94%) rename src/main/java/org/saturnclient/{saturnclient => }/cosmetics/cloaks/Cloaks.java (98%) rename src/main/java/org/saturnclient/{saturnclient => }/cosmetics/cloaks/GifDecoder.java (99%) rename src/main/java/org/saturnclient/{saturnclient => }/cosmetics/cloaks/utils/AnimatedCloakData.java (93%) rename src/main/java/org/saturnclient/{saturnclient => }/cosmetics/cloaks/utils/IdentifierUtils.java (98%) rename src/main/java/org/saturnclient/{saturnclient => }/cosmetics/cloaks/utils/RandomUtils.java (95%) diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/CloakFeatureRenderer.java similarity index 99% rename from src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java rename to src/main/java/org/saturnclient/cosmetics/CloakFeatureRenderer.java index 68280cb..356312c 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/CloakFeatureRenderer.java @@ -1,10 +1,10 @@ -package org.saturnclient.saturnclient.cosmetics; +package org.saturnclient.cosmetics; import java.util.Arrays; +import org.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.config.Config; -import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/Emotes.java b/src/main/java/org/saturnclient/cosmetics/Emotes.java similarity index 89% rename from src/main/java/org/saturnclient/saturnclient/cosmetics/Emotes.java rename to src/main/java/org/saturnclient/cosmetics/Emotes.java index 91a53d0..bc0353b 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/Emotes.java +++ b/src/main/java/org/saturnclient/cosmetics/Emotes.java @@ -1,4 +1,4 @@ -package org.saturnclient.saturnclient.cosmetics; +package org.saturnclient.cosmetics; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/HatFeatureRenderer.java similarity index 98% rename from src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java rename to src/main/java/org/saturnclient/cosmetics/HatFeatureRenderer.java index cabc440..c682358 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/HatFeatureRenderer.java @@ -1,4 +1,4 @@ -package org.saturnclient.saturnclient.cosmetics; +package org.saturnclient.cosmetics; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.SaturnClient; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java b/src/main/java/org/saturnclient/cosmetics/Hats.java similarity index 94% rename from src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java rename to src/main/java/org/saturnclient/cosmetics/Hats.java index ced3e77..948c998 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/Hats.java +++ b/src/main/java/org/saturnclient/cosmetics/Hats.java @@ -1,4 +1,4 @@ -package org.saturnclient.saturnclient.cosmetics; +package org.saturnclient.cosmetics; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java b/src/main/java/org/saturnclient/cosmetics/cloaks/Cloaks.java similarity index 98% rename from src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java rename to src/main/java/org/saturnclient/cosmetics/cloaks/Cloaks.java index d624942..54ac5ef 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/Cloaks.java +++ b/src/main/java/org/saturnclient/cosmetics/cloaks/Cloaks.java @@ -1,11 +1,9 @@ -package org.saturnclient.saturnclient.cosmetics.cloaks; +package org.saturnclient.cosmetics.cloaks; import net.minecraft.util.Identifier; import org.saturnclient.saturnclient.client.ServiceClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; -import org.saturnclient.saturnclient.cosmetics.cloaks.utils.AnimatedCloakData; -import org.saturnclient.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; @@ -17,6 +15,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.saturnclient.cosmetics.cloaks.utils.AnimatedCloakData; +import org.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; import org.saturnclient.saturnclient.SaturnClient; /** diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/GifDecoder.java b/src/main/java/org/saturnclient/cosmetics/cloaks/GifDecoder.java similarity index 99% rename from src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/GifDecoder.java rename to src/main/java/org/saturnclient/cosmetics/cloaks/GifDecoder.java index 5ab50d0..4cd9e5f 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/GifDecoder.java +++ b/src/main/java/org/saturnclient/cosmetics/cloaks/GifDecoder.java @@ -1,4 +1,4 @@ -package org.saturnclient.saturnclient.cosmetics.cloaks; +package org.saturnclient.cosmetics.cloaks; import java.awt.*; import java.awt.image.BufferedImage; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/utils/AnimatedCloakData.java b/src/main/java/org/saturnclient/cosmetics/cloaks/utils/AnimatedCloakData.java similarity index 93% rename from src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/utils/AnimatedCloakData.java rename to src/main/java/org/saturnclient/cosmetics/cloaks/utils/AnimatedCloakData.java index a38296c..a7a5479 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/utils/AnimatedCloakData.java +++ b/src/main/java/org/saturnclient/cosmetics/cloaks/utils/AnimatedCloakData.java @@ -1,4 +1,4 @@ -package org.saturnclient.saturnclient.cosmetics.cloaks.utils; +package org.saturnclient.cosmetics.cloaks.utils; import net.minecraft.util.Identifier; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/utils/IdentifierUtils.java b/src/main/java/org/saturnclient/cosmetics/cloaks/utils/IdentifierUtils.java similarity index 98% rename from src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/utils/IdentifierUtils.java rename to src/main/java/org/saturnclient/cosmetics/cloaks/utils/IdentifierUtils.java index 1ffd149..a9e752d 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/utils/IdentifierUtils.java +++ b/src/main/java/org/saturnclient/cosmetics/cloaks/utils/IdentifierUtils.java @@ -1,4 +1,4 @@ -package org.saturnclient.saturnclient.cosmetics.cloaks.utils; +package org.saturnclient.cosmetics.cloaks.utils; import org.saturnclient.saturnclient.SaturnClient; import net.minecraft.client.texture.NativeImage; diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/utils/RandomUtils.java b/src/main/java/org/saturnclient/cosmetics/cloaks/utils/RandomUtils.java similarity index 95% rename from src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/utils/RandomUtils.java rename to src/main/java/org/saturnclient/cosmetics/cloaks/utils/RandomUtils.java index 0e20412..744073f 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/cloaks/utils/RandomUtils.java +++ b/src/main/java/org/saturnclient/cosmetics/cloaks/utils/RandomUtils.java @@ -1,4 +1,4 @@ -package org.saturnclient.saturnclient.cosmetics.cloaks.utils; +package org.saturnclient.cosmetics.cloaks.utils; import java.util.Random; diff --git a/src/main/java/org/saturnclient/saturnclient/SaturnClient.java b/src/main/java/org/saturnclient/saturnclient/SaturnClient.java index 945e3d7..d0c77a9 100644 --- a/src/main/java/org/saturnclient/saturnclient/SaturnClient.java +++ b/src/main/java/org/saturnclient/saturnclient/SaturnClient.java @@ -6,13 +6,13 @@ import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.util.math.MatrixStack; +import org.saturnclient.cosmetics.Emotes; +import org.saturnclient.cosmetics.Hats; +import org.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.modules.ModManager; import org.saturnclient.saturnclient.client.ServiceClient; import org.saturnclient.saturnclient.config.Config; import org.saturnclient.saturnclient.config.manager.ConfigManager; -import org.saturnclient.saturnclient.cosmetics.Emotes; -import org.saturnclient.saturnclient.cosmetics.Hats; -import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.saturnclient.event.KeyInputHandler; import org.saturnclient.saturnclient.mixin.DrawContextAccessor; import org.saturnclient.ui2.RenderScope; diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index 442f7d9..a0f4b4f 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -3,10 +3,10 @@ package org.saturnclient.saturnclient.client; import java.util.UUID; import java.util.concurrent.TimeUnit; +import org.saturnclient.cosmetics.Hats; +import org.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.saturnclient.SaturnClient; 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; diff --git a/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java b/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java index 9726b3e..97cef55 100644 --- a/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java +++ b/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java @@ -7,8 +7,8 @@ import net.minecraft.client.render.entity.model.PlayerEntityModel; import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.entity.player.PlayerEntity; -import org.saturnclient.saturnclient.cosmetics.CloakFeatureRenderer; -import org.saturnclient.saturnclient.cosmetics.HatFeatureRenderer; +import org.saturnclient.cosmetics.CloakFeatureRenderer; +import org.saturnclient.cosmetics.HatFeatureRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java index 0bcd0f8..82d5dee 100644 --- a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java +++ b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java @@ -11,7 +11,7 @@ import com.kitfox.svg.SVGDiagram; import com.kitfox.svg.SVGUniverse; import org.jetbrains.annotations.Nullable; -import org.saturnclient.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; +import org.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.util.Identifier; diff --git a/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java b/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java index e087a43..96fa7f6 100644 --- a/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java +++ b/src/main/java/org/saturnclient/ui2/screens/EmoteWheel.java @@ -1,10 +1,10 @@ package org.saturnclient.ui2.screens; +import org.saturnclient.cosmetics.Emotes; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.ServiceClient; import org.saturnclient.saturnclient.config.AnimationConfig; import org.saturnclient.saturnclient.config.Config; -import org.saturnclient.saturnclient.cosmetics.Emotes; import org.saturnclient.ui2.SaturnScreen; import org.saturnclient.ui2.Utils; import org.saturnclient.ui2.anim.Fade; diff --git a/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java b/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java index c537a31..ad1ff7d 100644 --- a/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java @@ -1,9 +1,9 @@ package org.saturnclient.ui2.screens.cosmetics; +import org.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.config.AnimationConfig; -import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.ui2.resources.Textures; import org.saturnclient.ui2.SaturnScreen; import org.saturnclient.ui2.anim.Fade; diff --git a/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java b/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java index be2d1a5..6a15046 100644 --- a/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java @@ -1,9 +1,9 @@ package org.saturnclient.ui2.screens.cosmetics; +import org.saturnclient.cosmetics.Hats; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.config.AnimationConfig; -import org.saturnclient.saturnclient.cosmetics.Hats; import org.saturnclient.ui2.resources.Textures; import org.saturnclient.ui2.SaturnScreen; import org.saturnclient.ui2.anim.Fade; diff --git a/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java b/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java index e26449c..6518e91 100644 --- a/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java +++ b/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java @@ -1,11 +1,11 @@ package org.saturnclient.ui2.screens.store; +import org.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.ServiceClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.config.AnimationConfig; import org.saturnclient.saturnclient.config.Theme; -import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.ui2.SaturnScreen; import org.saturnclient.ui2.Utils; import org.saturnclient.ui2.anim.Fade; diff --git a/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java b/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java index 098e09d..ea32ee5 100644 --- a/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java +++ b/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java @@ -1,11 +1,11 @@ package org.saturnclient.ui2.screens.store; +import org.saturnclient.cosmetics.Hats; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.ServiceClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.config.AnimationConfig; import org.saturnclient.saturnclient.config.Theme; -import org.saturnclient.saturnclient.cosmetics.Hats; import org.saturnclient.ui2.SaturnScreen; import org.saturnclient.ui2.Utils; import org.saturnclient.ui2.anim.Fade; From 2b0f1dcb48b28d8f231eb02abf3467d9bcfaa63b Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 2 Mar 2026 02:59:09 +0100 Subject: [PATCH 06/19] Cosmetics refactor --- .../cosmetics/{ => cloak}/CloakFeatureRenderer.java | 3 +-- .../saturnclient/cosmetics/{cloaks => cloak}/Cloaks.java | 6 +++--- .../cosmetics/{cloaks => cloak}/GifDecoder.java | 2 +- .../{cloaks => cloak}/utils/AnimatedCloakData.java | 2 +- .../cosmetics/{cloaks => cloak}/utils/IdentifierUtils.java | 2 +- .../cosmetics/{cloaks => cloak}/utils/RandomUtils.java | 2 +- .../cosmetics/{ => hat}/HatFeatureRenderer.java | 2 +- .../java/org/saturnclient/cosmetics/{ => hat}/Hats.java | 2 +- .../java/org/saturnclient/saturnclient/SaturnClient.java | 4 ++-- .../org/saturnclient/saturnclient/client/ServiceClient.java | 4 ++-- .../saturnclient/mixin/PlayerEntityRendererMixin.java | 4 ++-- .../java/org/saturnclient/ui2/resources/SvgTexture.java | 2 +- .../org/saturnclient/ui2/screens/cosmetics/CloakMenu.java | 2 +- .../org/saturnclient/ui2/screens/cosmetics/HatMenu.java | 2 +- .../java/org/saturnclient/ui2/screens/store/CloakStore.java | 2 +- .../java/org/saturnclient/ui2/screens/store/HatStore.java | 2 +- 16 files changed, 21 insertions(+), 22 deletions(-) rename src/main/java/org/saturnclient/cosmetics/{ => cloak}/CloakFeatureRenderer.java (99%) rename src/main/java/org/saturnclient/cosmetics/{cloaks => cloak}/Cloaks.java (98%) rename src/main/java/org/saturnclient/cosmetics/{cloaks => cloak}/GifDecoder.java (99%) rename src/main/java/org/saturnclient/cosmetics/{cloaks => cloak}/utils/AnimatedCloakData.java (94%) rename src/main/java/org/saturnclient/cosmetics/{cloaks => cloak}/utils/IdentifierUtils.java (98%) rename src/main/java/org/saturnclient/cosmetics/{cloaks => cloak}/utils/RandomUtils.java (96%) rename src/main/java/org/saturnclient/cosmetics/{ => hat}/HatFeatureRenderer.java (98%) rename src/main/java/org/saturnclient/cosmetics/{ => hat}/Hats.java (95%) diff --git a/src/main/java/org/saturnclient/cosmetics/CloakFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/cloak/CloakFeatureRenderer.java similarity index 99% rename from src/main/java/org/saturnclient/cosmetics/CloakFeatureRenderer.java rename to src/main/java/org/saturnclient/cosmetics/cloak/CloakFeatureRenderer.java index 356312c..a91ff29 100644 --- a/src/main/java/org/saturnclient/cosmetics/CloakFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/cloak/CloakFeatureRenderer.java @@ -1,8 +1,7 @@ -package org.saturnclient.cosmetics; +package org.saturnclient.cosmetics.cloak; import java.util.Arrays; -import org.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.config.Config; diff --git a/src/main/java/org/saturnclient/cosmetics/cloaks/Cloaks.java b/src/main/java/org/saturnclient/cosmetics/cloak/Cloaks.java similarity index 98% rename from src/main/java/org/saturnclient/cosmetics/cloaks/Cloaks.java rename to src/main/java/org/saturnclient/cosmetics/cloak/Cloaks.java index 54ac5ef..ef54f85 100644 --- a/src/main/java/org/saturnclient/cosmetics/cloaks/Cloaks.java +++ b/src/main/java/org/saturnclient/cosmetics/cloak/Cloaks.java @@ -1,4 +1,4 @@ -package org.saturnclient.cosmetics.cloaks; +package org.saturnclient.cosmetics.cloak; import net.minecraft.util.Identifier; @@ -15,8 +15,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import org.saturnclient.cosmetics.cloaks.utils.AnimatedCloakData; -import org.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; +import org.saturnclient.cosmetics.cloak.utils.AnimatedCloakData; +import org.saturnclient.cosmetics.cloak.utils.IdentifierUtils; import org.saturnclient.saturnclient.SaturnClient; /** diff --git a/src/main/java/org/saturnclient/cosmetics/cloaks/GifDecoder.java b/src/main/java/org/saturnclient/cosmetics/cloak/GifDecoder.java similarity index 99% rename from src/main/java/org/saturnclient/cosmetics/cloaks/GifDecoder.java rename to src/main/java/org/saturnclient/cosmetics/cloak/GifDecoder.java index 4cd9e5f..dcb4b2b 100644 --- a/src/main/java/org/saturnclient/cosmetics/cloaks/GifDecoder.java +++ b/src/main/java/org/saturnclient/cosmetics/cloak/GifDecoder.java @@ -1,4 +1,4 @@ -package org.saturnclient.cosmetics.cloaks; +package org.saturnclient.cosmetics.cloak; import java.awt.*; import java.awt.image.BufferedImage; diff --git a/src/main/java/org/saturnclient/cosmetics/cloaks/utils/AnimatedCloakData.java b/src/main/java/org/saturnclient/cosmetics/cloak/utils/AnimatedCloakData.java similarity index 94% rename from src/main/java/org/saturnclient/cosmetics/cloaks/utils/AnimatedCloakData.java rename to src/main/java/org/saturnclient/cosmetics/cloak/utils/AnimatedCloakData.java index a7a5479..ca92aa0 100644 --- a/src/main/java/org/saturnclient/cosmetics/cloaks/utils/AnimatedCloakData.java +++ b/src/main/java/org/saturnclient/cosmetics/cloak/utils/AnimatedCloakData.java @@ -1,4 +1,4 @@ -package org.saturnclient.cosmetics.cloaks.utils; +package org.saturnclient.cosmetics.cloak.utils; import net.minecraft.util.Identifier; diff --git a/src/main/java/org/saturnclient/cosmetics/cloaks/utils/IdentifierUtils.java b/src/main/java/org/saturnclient/cosmetics/cloak/utils/IdentifierUtils.java similarity index 98% rename from src/main/java/org/saturnclient/cosmetics/cloaks/utils/IdentifierUtils.java rename to src/main/java/org/saturnclient/cosmetics/cloak/utils/IdentifierUtils.java index a9e752d..93fb940 100644 --- a/src/main/java/org/saturnclient/cosmetics/cloaks/utils/IdentifierUtils.java +++ b/src/main/java/org/saturnclient/cosmetics/cloak/utils/IdentifierUtils.java @@ -1,4 +1,4 @@ -package org.saturnclient.cosmetics.cloaks.utils; +package org.saturnclient.cosmetics.cloak.utils; import org.saturnclient.saturnclient.SaturnClient; import net.minecraft.client.texture.NativeImage; diff --git a/src/main/java/org/saturnclient/cosmetics/cloaks/utils/RandomUtils.java b/src/main/java/org/saturnclient/cosmetics/cloak/utils/RandomUtils.java similarity index 96% rename from src/main/java/org/saturnclient/cosmetics/cloaks/utils/RandomUtils.java rename to src/main/java/org/saturnclient/cosmetics/cloak/utils/RandomUtils.java index 744073f..b555d83 100644 --- a/src/main/java/org/saturnclient/cosmetics/cloaks/utils/RandomUtils.java +++ b/src/main/java/org/saturnclient/cosmetics/cloak/utils/RandomUtils.java @@ -1,4 +1,4 @@ -package org.saturnclient.cosmetics.cloaks.utils; +package org.saturnclient.cosmetics.cloak.utils; import java.util.Random; diff --git a/src/main/java/org/saturnclient/cosmetics/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java similarity index 98% rename from src/main/java/org/saturnclient/cosmetics/HatFeatureRenderer.java rename to src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java index c682358..7608246 100644 --- a/src/main/java/org/saturnclient/cosmetics/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java @@ -1,4 +1,4 @@ -package org.saturnclient.cosmetics; +package org.saturnclient.cosmetics.hat; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.SaturnClient; diff --git a/src/main/java/org/saturnclient/cosmetics/Hats.java b/src/main/java/org/saturnclient/cosmetics/hat/Hats.java similarity index 95% rename from src/main/java/org/saturnclient/cosmetics/Hats.java rename to src/main/java/org/saturnclient/cosmetics/hat/Hats.java index 948c998..6aee225 100644 --- a/src/main/java/org/saturnclient/cosmetics/Hats.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/Hats.java @@ -1,4 +1,4 @@ -package org.saturnclient.cosmetics; +package org.saturnclient.cosmetics.hat; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/saturnclient/saturnclient/SaturnClient.java b/src/main/java/org/saturnclient/saturnclient/SaturnClient.java index d0c77a9..9d2db7f 100644 --- a/src/main/java/org/saturnclient/saturnclient/SaturnClient.java +++ b/src/main/java/org/saturnclient/saturnclient/SaturnClient.java @@ -7,8 +7,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.util.math.MatrixStack; import org.saturnclient.cosmetics.Emotes; -import org.saturnclient.cosmetics.Hats; -import org.saturnclient.cosmetics.cloaks.Cloaks; +import org.saturnclient.cosmetics.cloak.Cloaks; +import org.saturnclient.cosmetics.hat.Hats; import org.saturnclient.modules.ModManager; import org.saturnclient.saturnclient.client.ServiceClient; import org.saturnclient.saturnclient.config.Config; diff --git a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java index a0f4b4f..4102704 100644 --- a/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java +++ b/src/main/java/org/saturnclient/saturnclient/client/ServiceClient.java @@ -3,8 +3,8 @@ package org.saturnclient.saturnclient.client; import java.util.UUID; import java.util.concurrent.TimeUnit; -import org.saturnclient.cosmetics.Hats; -import org.saturnclient.cosmetics.cloaks.Cloaks; +import org.saturnclient.cosmetics.cloak.Cloaks; +import org.saturnclient.cosmetics.hat.Hats; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; diff --git a/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java b/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java index 97cef55..5a9228e 100644 --- a/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java +++ b/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java @@ -7,8 +7,8 @@ import net.minecraft.client.render.entity.model.PlayerEntityModel; import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.entity.player.PlayerEntity; -import org.saturnclient.cosmetics.CloakFeatureRenderer; -import org.saturnclient.cosmetics.HatFeatureRenderer; +import org.saturnclient.cosmetics.cloak.CloakFeatureRenderer; +import org.saturnclient.cosmetics.hat.HatFeatureRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java index 82d5dee..6cc79d3 100644 --- a/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java +++ b/src/main/java/org/saturnclient/ui2/resources/SvgTexture.java @@ -11,7 +11,7 @@ import com.kitfox.svg.SVGDiagram; import com.kitfox.svg.SVGUniverse; import org.jetbrains.annotations.Nullable; -import org.saturnclient.cosmetics.cloaks.utils.IdentifierUtils; +import org.saturnclient.cosmetics.cloak.utils.IdentifierUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.util.Identifier; diff --git a/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java b/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java index ad1ff7d..724407a 100644 --- a/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/cosmetics/CloakMenu.java @@ -1,6 +1,6 @@ package org.saturnclient.ui2.screens.cosmetics; -import org.saturnclient.cosmetics.cloaks.Cloaks; +import org.saturnclient.cosmetics.cloak.Cloaks; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.config.AnimationConfig; diff --git a/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java b/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java index 6a15046..f21723a 100644 --- a/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/cosmetics/HatMenu.java @@ -1,6 +1,6 @@ package org.saturnclient.ui2.screens.cosmetics; -import org.saturnclient.cosmetics.Hats; +import org.saturnclient.cosmetics.hat.Hats; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import org.saturnclient.saturnclient.config.AnimationConfig; diff --git a/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java b/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java index 6518e91..2978972 100644 --- a/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java +++ b/src/main/java/org/saturnclient/ui2/screens/store/CloakStore.java @@ -1,6 +1,6 @@ package org.saturnclient.ui2.screens.store; -import org.saturnclient.cosmetics.cloaks.Cloaks; +import org.saturnclient.cosmetics.cloak.Cloaks; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.ServiceClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; diff --git a/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java b/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java index ea32ee5..328f701 100644 --- a/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java +++ b/src/main/java/org/saturnclient/ui2/screens/store/HatStore.java @@ -1,6 +1,6 @@ package org.saturnclient.ui2.screens.store; -import org.saturnclient.cosmetics.Hats; +import org.saturnclient.cosmetics.hat.Hats; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.ServiceClient; import org.saturnclient.saturnclient.client.player.SaturnPlayer; From 178fb1a484de88fd87b303e1cc953c5a79aac042 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 2 Mar 2026 15:01:18 +0100 Subject: [PATCH 07/19] Tesiting 3d obj rendering --- build.gradle | 3 + .../cosmetics/hat/HatFeatureRenderer.java | 56 ++++---------- .../cosmetics/obj/ObjRenderer.java | 74 +++++++++++++++++++ 3 files changed, 91 insertions(+), 42 deletions(-) create mode 100644 src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java diff --git a/build.gradle b/build.gradle index 48d842a..0a1aa1f 100644 --- a/build.gradle +++ b/build.gradle @@ -87,6 +87,9 @@ dependencies { modApi "dev.felnull:special-model-loader:1.4.0+pre.1" include "dev.felnull:special-model-loader:1.4.0+pre.1" + implementation "de.javagl:obj:0.4.0" + include "de.javagl:obj:0.4.0" + // SVG Rendering Library include implementation("com.formdev:svgSalamander:1.1.4") diff --git a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java index 7608246..3656803 100644 --- a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java @@ -1,62 +1,34 @@ package org.saturnclient.cosmetics.hat; -import org.saturnclient.saturnclient.client.player.SaturnPlayer; -import org.saturnclient.saturnclient.SaturnClient; -import net.minecraft.client.render.OverlayTexture; +import java.io.IOException; + +import org.saturnclient.cosmetics.obj.ObjRenderer; + +import de.javagl.obj.Obj; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.render.entity.feature.FeatureRendererContext; import net.minecraft.client.render.entity.model.PlayerEntityModel; import net.minecraft.client.render.entity.state.PlayerEntityRenderState; -import net.minecraft.client.render.item.ItemRenderer; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.EquippableComponent; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.item.ModelTransformationMode; import net.minecraft.util.Identifier; public class HatFeatureRenderer extends FeatureRenderer { + static Identifier HAT = Identifier.of("saturnclient", "models/item/horns/horns.obj"); + Obj obj; + public HatFeatureRenderer(FeatureRendererContext context) { super(context); + try { + this.obj = ObjRenderer.loadObj(HAT); + } catch (IOException e) { + e.printStackTrace(); + } } @Override public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, PlayerEntityRenderState state, float limbAngle, float limbDistance) { - ItemStack headItem = state.equippedHeadStack; - SaturnPlayer player = SaturnPlayer.get(state.name); - - if (!headItem.isEmpty() || state.invisible || player == null || player.hat.isEmpty()) { - return; - } - - matrices.push(); - - this.getContextModel().head.rotate(matrices); - matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_X.rotationDegrees(180.0f)); - matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Y.rotationDegrees(180.0f)); - - ItemStack customHat = new ItemStack(Items.STICK); - customHat.set(DataComponentTypes.ITEM_MODEL, - Identifier.of("saturnclient:hat_" + player.hat)); - customHat.set(DataComponentTypes.EQUIPPABLE, - EquippableComponent.builder(EquipmentSlot.HEAD).build()); - - ItemRenderer itemRenderer = SaturnClient.client.getItemRenderer(); - - itemRenderer.renderItem( - customHat, - ModelTransformationMode.THIRD_PERSON_RIGHT_HAND, - light, - OverlayTexture.DEFAULT_UV, - matrices, - vertexConsumers, - null, - 0); - - matrices.pop(); + ObjRenderer.renderObj(this.obj, matrices, vertexConsumers, light, 0); } } \ No newline at end of file diff --git a/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java b/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java new file mode 100644 index 0000000..7c68a08 --- /dev/null +++ b/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java @@ -0,0 +1,74 @@ +package org.saturnclient.cosmetics.obj; + +import java.io.IOException; +import java.io.InputStream; + +import de.javagl.obj.FloatTuple; +import de.javagl.obj.Obj; +import de.javagl.obj.ObjFace; +import de.javagl.obj.ObjReader; +import de.javagl.obj.ObjUtils; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Identifier; + +public class ObjRenderer { + public static Obj loadObj(Identifier objId) throws IOException { + try (InputStream is = MinecraftClient.getInstance().getResourceManager() + .getResource(objId).get().getInputStream()) { + return ObjUtils.convertToRenderable(ObjReader.read(is)); + } + } + + public static void renderObj(Obj obj, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, + int overlay) { + VertexConsumer consumer = vertexConsumers.getBuffer( + RenderLayer.getEntityAlpha(Identifier.of("textures/misc/white.png"))); + + MatrixStack.Entry entry = matrices.peek(); + + int faces = obj.getNumFaces(); + + for (int f = 0; f < faces; f++) { + ObjFace face = obj.getFace(f); + + for (int i = 0; i < 3; i++) { + writeVertex(obj, face, i, consumer, entry, light, overlay); + } + } + } + + /** Write a single vertex to the VertexConsumer using the OBJ FloatTuple */ + private static void writeVertex(Obj obj, ObjFace face, int index, VertexConsumer consumer, MatrixStack.Entry matrix, + int light, int overlay) { + FloatTuple pos = obj.getVertex(face.getVertexIndex(index)); + float x = pos.getX(); + float y = pos.getY(); + float z = pos.getZ(); + + // Default normal + float nx = 0f; + float ny = 1f; + float nz = 0f; + + // Use OBJ normal if available + int normalIndex = face.getNormalIndex(index); + if (normalIndex >= 0) { + FloatTuple n = obj.getNormal(normalIndex); + nx = n.getX(); + ny = n.getY(); + nz = n.getZ(); + } + + consumer.vertex(matrix, x, y, z) + .color(255, 255, 255, 255) + .texture(0f, 0f) + .overlay(overlay) + .light(light) + .normal(matrix, nx, ny, nz); + } +} \ No newline at end of file From e3ad918755937e308db289c4fdabea63c042f72c Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 02:37:53 +0100 Subject: [PATCH 08/19] Working obj rendering --- .../java/org/saturnclient/cosmetics/obj/ObjRenderer.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java b/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java index 7c68a08..8d6a413 100644 --- a/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java @@ -7,7 +7,6 @@ import de.javagl.obj.FloatTuple; import de.javagl.obj.Obj; import de.javagl.obj.ObjFace; import de.javagl.obj.ObjReader; -import de.javagl.obj.ObjUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.RenderLayer; @@ -20,7 +19,7 @@ public class ObjRenderer { public static Obj loadObj(Identifier objId) throws IOException { try (InputStream is = MinecraftClient.getInstance().getResourceManager() .getResource(objId).get().getInputStream()) { - return ObjUtils.convertToRenderable(ObjReader.read(is)); + return ObjReader.read(is); } } @@ -33,10 +32,14 @@ public class ObjRenderer { int faces = obj.getNumFaces(); + System.out.println("Faces " + faces + ", vertices " + obj.getNumVertices()); + for (int f = 0; f < faces; f++) { ObjFace face = obj.getFace(f); + int vertices = face.getNumVertices(); - for (int i = 0; i < 3; i++) { + // Reverse winding order: OBJ is CCW, Minecraft expects CW + for (int i = vertices - 1; i >= 0; i--) { writeVertex(obj, face, i, consumer, entry, light, overlay); } } From 80684f7e07fbea2b49c6bd75fcdeb0a16bf59aba Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 02:51:06 +0100 Subject: [PATCH 09/19] Working mtl obj rendering --- .../cosmetics/hat/HatFeatureRenderer.java | 7 +- .../cosmetics/obj/ObjRenderer.java | 103 +++++++++++++----- .../assets/saturnclient/models/item/black.mtl | 2 +- .../assets/saturnclient/models/item/white.mtl | 2 +- 4 files changed, 84 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java index 3656803..3d03d98 100644 --- a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java @@ -1,9 +1,11 @@ package org.saturnclient.cosmetics.hat; import java.io.IOException; +import java.util.Map; import org.saturnclient.cosmetics.obj.ObjRenderer; +import de.javagl.obj.Mtl; import de.javagl.obj.Obj; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.feature.FeatureRenderer; @@ -15,12 +17,15 @@ import net.minecraft.util.Identifier; public class HatFeatureRenderer extends FeatureRenderer { static Identifier HAT = Identifier.of("saturnclient", "models/item/horns/horns.obj"); + static Identifier BLACK_MTL = Identifier.of("saturnclient", "models/item/black.mtl"); Obj obj; + Map mtl; public HatFeatureRenderer(FeatureRendererContext context) { super(context); try { this.obj = ObjRenderer.loadObj(HAT); + this.mtl = ObjRenderer.loadMtl(BLACK_MTL); } catch (IOException e) { e.printStackTrace(); } @@ -29,6 +34,6 @@ public class HatFeatureRenderer extends FeatureRenderer loadMtl(Identifier mtlId) throws IOException { + try (InputStream is = MinecraftClient.getInstance().getResourceManager() + .getResource(mtlId).get().getInputStream()) { + List mtlList = MtlReader.read(is); + Map mtlMap = new java.util.LinkedHashMap<>(); + for (Mtl mtl : mtlList) { + mtlMap.put(mtl.getName(), mtl); + } + return mtlMap; + } + } + + public static void renderObj(Obj obj, Map mtlMap, MatrixStack matrices, + VertexConsumerProvider vertexConsumers, int light, int overlay) { MatrixStack.Entry entry = matrices.peek(); - int faces = obj.getNumFaces(); + Map materialGroups = ObjSplitting.splitByMaterialGroups(obj); - System.out.println("Faces " + faces + ", vertices " + obj.getNumVertices()); + for (Map.Entry group : materialGroups.entrySet()) { + String materialName = group.getKey(); + Obj groupObj = group.getValue(); - for (int f = 0; f < faces; f++) { - ObjFace face = obj.getFace(f); - int vertices = face.getNumVertices(); + Mtl mtl = mtlMap != null ? mtlMap.get(materialName) : null; - // Reverse winding order: OBJ is CCW, Minecraft expects CW - for (int i = vertices - 1; i >= 0; i--) { - writeVertex(obj, face, i, consumer, entry, light, overlay); + // Resolve texture identifier using same logic as ObjUnbakedModelModel + Identifier texture = Identifier.of("minecraft:textures/misc/white.png"); + + if (mtl != null) { + String mapKd = mtl.getMapKd(); + if (mapKd != null) { + // "#key" references are not resolvable at runtime without a texture map, + // so we only support direct resource location strings here + if (!mapKd.startsWith("#")) { + texture = Identifier.of(mapKd); + } + } + } + + // Diffuse color (Kd) + float r = 1f, g = 1f, b = 1f; + if (mtl != null) { + FloatTuple kd = mtl.getKd(); + if (kd != null) { + r = kd.getX(); + g = kd.getY(); + b = kd.getZ(); + } + } + + VertexConsumer consumer = vertexConsumers.getBuffer(RenderLayer.getEntityAlpha(texture)); + + int faces = groupObj.getNumFaces(); + final float fr = r, fg = g, fb = b; + + for (int f = 0; f < faces; f++) { + ObjFace face = groupObj.getFace(f); + int verts = face.getNumVertices(); + + // Your original winding order logic, untouched + for (int i = verts - 1; i >= 0; i--) { + writeVertex(groupObj, face, i, consumer, entry, light, overlay, fr, fg, fb); + } } } } - /** Write a single vertex to the VertexConsumer using the OBJ FloatTuple */ - private static void writeVertex(Obj obj, ObjFace face, int index, VertexConsumer consumer, MatrixStack.Entry matrix, - int light, int overlay) { + private static void writeVertex(Obj obj, ObjFace face, int index, VertexConsumer consumer, + MatrixStack.Entry matrix, int light, int overlay, + float r, float g, float b) { + FloatTuple pos = obj.getVertex(face.getVertexIndex(index)); float x = pos.getX(); float y = pos.getY(); float z = pos.getZ(); - // Default normal - float nx = 0f; - float ny = 1f; - float nz = 0f; - - // Use OBJ normal if available + float nx = 0f, ny = 1f, nz = 0f; int normalIndex = face.getNormalIndex(index); if (normalIndex >= 0) { FloatTuple n = obj.getNormal(normalIndex); @@ -67,9 +108,17 @@ public class ObjRenderer { nz = n.getZ(); } + float u = 0f, v = 0f; + int texIndex = face.getTexCoordIndex(index); + if (texIndex >= 0) { + FloatTuple tc = obj.getTexCoord(texIndex); + u = tc.getX(); + v = 1f - tc.getY(); // Flip V: OBJ bottom-left origin -> Minecraft top-left + } + consumer.vertex(matrix, x, y, z) - .color(255, 255, 255, 255) - .texture(0f, 0f) + .color(r, g, b, 1f) + .texture(u, v) .overlay(overlay) .light(light) .normal(matrix, nx, ny, nz); diff --git a/src/main/resources/assets/saturnclient/models/item/black.mtl b/src/main/resources/assets/saturnclient/models/item/black.mtl index 6670390..3661766 100644 --- a/src/main/resources/assets/saturnclient/models/item/black.mtl +++ b/src/main/resources/assets/saturnclient/models/item/black.mtl @@ -10,4 +10,4 @@ Ke 0.000000 0.000000 0.000000 Ni 1.450000 d 1.000000 illum 2 -map_Kd saturnclient:item/halo_black +map_Kd saturnclient:textures/item/halo_black.png diff --git a/src/main/resources/assets/saturnclient/models/item/white.mtl b/src/main/resources/assets/saturnclient/models/item/white.mtl index f273f55..9c0dc53 100644 --- a/src/main/resources/assets/saturnclient/models/item/white.mtl +++ b/src/main/resources/assets/saturnclient/models/item/white.mtl @@ -10,4 +10,4 @@ Ke 0.000000 0.000000 0.000000 Ni 1.450000 d 1.000000 illum 2 -map_Kd saturnclient:item/halo +map_Kd saturnclient:textures/item/halo.png From 2f41fc080c421b4a7e4292c9c34cb0906053dd38 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 03:06:03 +0100 Subject: [PATCH 10/19] Working custom obj hat --- .../cosmetics/hat/HatFeatureRenderer.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java index 3d03d98..ea55d4f 100644 --- a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java @@ -4,15 +4,18 @@ import java.io.IOException; import java.util.Map; import org.saturnclient.cosmetics.obj.ObjRenderer; +import org.saturnclient.saturnclient.client.player.SaturnPlayer; import de.javagl.obj.Mtl; import de.javagl.obj.Obj; +import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.render.entity.feature.FeatureRendererContext; import net.minecraft.client.render.entity.model.PlayerEntityModel; import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; public class HatFeatureRenderer extends FeatureRenderer { @@ -34,6 +37,25 @@ public class HatFeatureRenderer extends FeatureRenderer Date: Tue, 3 Mar 2026 03:40:44 +0100 Subject: [PATCH 11/19] Hat model caching --- .../cosmetics/hat/HatFeatureRenderer.java | 13 ++--- .../saturnclient/cosmetics/obj/ObjModel.java | 57 +++++++++++++++++++ .../cosmetics/obj/ObjRenderer.java | 2 - .../assets/saturnclient/items/hat_halo.json | 6 -- .../saturnclient/items/hat_halo_black.json | 6 -- .../saturnclient/items/hat_horns_black.json | 6 -- .../saturnclient/items/hat_horns_white.json | 6 -- .../models/{item => cosmetic}/black.mtl | 0 .../halo/halo.obj => cosmetic/halo/model.obj} | 0 .../horns.obj => cosmetic/horns/model.obj} | 0 .../models/{item => cosmetic}/white.mtl | 0 .../saturnclient/models/item/halo/black.json | 13 ----- .../saturnclient/models/item/halo/white.json | 13 ----- .../saturnclient/models/item/horns/black.json | 13 ----- .../saturnclient/models/item/horns/white.json | 13 ----- 15 files changed, 62 insertions(+), 86 deletions(-) create mode 100644 src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java delete mode 100644 src/main/resources/assets/saturnclient/items/hat_halo.json delete mode 100644 src/main/resources/assets/saturnclient/items/hat_halo_black.json delete mode 100644 src/main/resources/assets/saturnclient/items/hat_horns_black.json delete mode 100644 src/main/resources/assets/saturnclient/items/hat_horns_white.json rename src/main/resources/assets/saturnclient/models/{item => cosmetic}/black.mtl (100%) rename src/main/resources/assets/saturnclient/models/{item/halo/halo.obj => cosmetic/halo/model.obj} (100%) rename src/main/resources/assets/saturnclient/models/{item/horns/horns.obj => cosmetic/horns/model.obj} (100%) rename src/main/resources/assets/saturnclient/models/{item => cosmetic}/white.mtl (100%) delete mode 100644 src/main/resources/assets/saturnclient/models/item/halo/black.json delete mode 100644 src/main/resources/assets/saturnclient/models/item/halo/white.json delete mode 100644 src/main/resources/assets/saturnclient/models/item/horns/black.json delete mode 100644 src/main/resources/assets/saturnclient/models/item/horns/white.json diff --git a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java index ea55d4f..ef06149 100644 --- a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java @@ -3,11 +3,11 @@ package org.saturnclient.cosmetics.hat; import java.io.IOException; import java.util.Map; +import org.saturnclient.cosmetics.obj.ObjModel; import org.saturnclient.cosmetics.obj.ObjRenderer; import org.saturnclient.saturnclient.client.player.SaturnPlayer; import de.javagl.obj.Mtl; -import de.javagl.obj.Obj; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.feature.FeatureRenderer; @@ -19,15 +19,12 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; public class HatFeatureRenderer extends FeatureRenderer { - static Identifier HAT = Identifier.of("saturnclient", "models/item/horns/horns.obj"); - static Identifier BLACK_MTL = Identifier.of("saturnclient", "models/item/black.mtl"); - Obj obj; + static Identifier BLACK_MTL = Identifier.of("saturnclient", "models/cosmetic/black.mtl"); Map mtl; public HatFeatureRenderer(FeatureRendererContext context) { super(context); try { - this.obj = ObjRenderer.loadObj(HAT); this.mtl = ObjRenderer.loadMtl(BLACK_MTL); } catch (IOException e) { e.printStackTrace(); @@ -52,9 +49,9 @@ public class HatFeatureRenderer extends FeatureRenderer loadedObjModels = new HashMap<>(); + + public record Config( + @JsonProperty("transform") Transform transform) { + + @JsonFormat(shape = JsonFormat.Shape.ARRAY) + public record Transform(double x, double y, double z) { + } + } + + Obj obj; + Config config; + + public static ObjModel of(Identifier obj) { + if (loadedObjModels.containsKey(obj)) + return loadedObjModels.get(obj); + + ObjModel o = new ObjModel(obj); + loadedObjModels.put(obj, o); + return o; + } + + ObjModel(Identifier identifier) { + Identifier obj = Identifier.of(identifier.getNamespace(), identifier.getPath() + ".obj"); + System.out.println(obj); + // Identifier json = Identifier.of(identifier.getNamespace(), identifier.getPath() + ".json"); + + try { + this.obj = ObjRenderer.loadObj(obj); + } catch (IOException e) { + e.printStackTrace(); + } + + Identifier.of(obj.toString()); + } + + public void render(Map mtlMap, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, + int overlay) { + ObjRenderer.renderObj(this.obj, mtlMap, matrices, vertexConsumers, light, overlay); + } +} diff --git a/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java b/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java index 420323c..6f59fe6 100644 --- a/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java @@ -15,7 +15,6 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; public class ObjRenderer { - public static Obj loadObj(Identifier objId) throws IOException { try (InputStream is = MinecraftClient.getInstance().getResourceManager() .getResource(objId).get().getInputStream()) { @@ -37,7 +36,6 @@ public class ObjRenderer { public static void renderObj(Obj obj, Map mtlMap, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { - MatrixStack.Entry entry = matrices.peek(); Map materialGroups = ObjSplitting.splitByMaterialGroups(obj); diff --git a/src/main/resources/assets/saturnclient/items/hat_halo.json b/src/main/resources/assets/saturnclient/items/hat_halo.json deleted file mode 100644 index 9666890..0000000 --- a/src/main/resources/assets/saturnclient/items/hat_halo.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "saturnclient:item/halo/white" - } -} diff --git a/src/main/resources/assets/saturnclient/items/hat_halo_black.json b/src/main/resources/assets/saturnclient/items/hat_halo_black.json deleted file mode 100644 index cb7e0c7..0000000 --- a/src/main/resources/assets/saturnclient/items/hat_halo_black.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "saturnclient:item/halo/black" - } -} diff --git a/src/main/resources/assets/saturnclient/items/hat_horns_black.json b/src/main/resources/assets/saturnclient/items/hat_horns_black.json deleted file mode 100644 index 610dd63..0000000 --- a/src/main/resources/assets/saturnclient/items/hat_horns_black.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "saturnclient:item/horns/black" - } -} diff --git a/src/main/resources/assets/saturnclient/items/hat_horns_white.json b/src/main/resources/assets/saturnclient/items/hat_horns_white.json deleted file mode 100644 index e81956c..0000000 --- a/src/main/resources/assets/saturnclient/items/hat_horns_white.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "saturnclient:item/horns/white" - } -} diff --git a/src/main/resources/assets/saturnclient/models/item/black.mtl b/src/main/resources/assets/saturnclient/models/cosmetic/black.mtl similarity index 100% rename from src/main/resources/assets/saturnclient/models/item/black.mtl rename to src/main/resources/assets/saturnclient/models/cosmetic/black.mtl diff --git a/src/main/resources/assets/saturnclient/models/item/halo/halo.obj b/src/main/resources/assets/saturnclient/models/cosmetic/halo/model.obj similarity index 100% rename from src/main/resources/assets/saturnclient/models/item/halo/halo.obj rename to src/main/resources/assets/saturnclient/models/cosmetic/halo/model.obj diff --git a/src/main/resources/assets/saturnclient/models/item/horns/horns.obj b/src/main/resources/assets/saturnclient/models/cosmetic/horns/model.obj similarity index 100% rename from src/main/resources/assets/saturnclient/models/item/horns/horns.obj rename to src/main/resources/assets/saturnclient/models/cosmetic/horns/model.obj diff --git a/src/main/resources/assets/saturnclient/models/item/white.mtl b/src/main/resources/assets/saturnclient/models/cosmetic/white.mtl similarity index 100% rename from src/main/resources/assets/saturnclient/models/item/white.mtl rename to src/main/resources/assets/saturnclient/models/cosmetic/white.mtl diff --git a/src/main/resources/assets/saturnclient/models/item/halo/black.json b/src/main/resources/assets/saturnclient/models/item/halo/black.json deleted file mode 100644 index bd402ad..0000000 --- a/src/main/resources/assets/saturnclient/models/item/halo/black.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "special-model-loader:builtin/obj", - "model": "saturnclient:models/item/halo/halo.obj", - "mtl_override": "saturnclient:models/item/black.mtl", - "flip_v": true, - "display": { - "thirdperson_righthand": { - "rotation": [0, 0, 0], - "translation": [1.5, 12, 1.5], - "scale": [0.2, 0.2, 0.2] - } - } -} diff --git a/src/main/resources/assets/saturnclient/models/item/halo/white.json b/src/main/resources/assets/saturnclient/models/item/halo/white.json deleted file mode 100644 index 6265076..0000000 --- a/src/main/resources/assets/saturnclient/models/item/halo/white.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "special-model-loader:builtin/obj", - "model": "saturnclient:models/item/halo/halo.obj", - "mtl_override": "saturnclient:models/item/white.mtl", - "flip_v": true, - "display": { - "thirdperson_righthand": { - "rotation": [0, 0, 0], - "translation": [1.5, 12, 1.5], - "scale": [0.2, 0.2, 0.2] - } - } -} diff --git a/src/main/resources/assets/saturnclient/models/item/horns/black.json b/src/main/resources/assets/saturnclient/models/item/horns/black.json deleted file mode 100644 index effa342..0000000 --- a/src/main/resources/assets/saturnclient/models/item/horns/black.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "special-model-loader:builtin/obj", - "model": "saturnclient:models/item/horns/horns.obj", - "mtl_override": "saturnclient:models/item/black.mtl", - "flip_v": true, - "display": { - "thirdperson_righthand": { - "rotation": [0, 0, 0], - "translation": [2, 6, 2], - "scale": [0.25, 0.25, 0.25] - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/models/item/horns/white.json b/src/main/resources/assets/saturnclient/models/item/horns/white.json deleted file mode 100644 index 1001f92..0000000 --- a/src/main/resources/assets/saturnclient/models/item/horns/white.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "special-model-loader:builtin/obj", - "model": "saturnclient:models/item/horns/horns.obj", - "mtl_override": "saturnclient:models/item/white.mtl", - "flip_v": true, - "display": { - "thirdperson_righthand": { - "rotation": [0, 0, 0], - "translation": [2, 6, 2], - "scale": [0.25, 0.25, 0.25] - } - } -} \ No newline at end of file From 92b310e5e297e9b45ec5659b63498d8b475b357e Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 03:50:56 +0100 Subject: [PATCH 12/19] Working json for model --- .../cosmetics/hat/HatFeatureRenderer.java | 4 -- .../saturnclient/cosmetics/obj/ObjModel.java | 43 ++++++++++++++++--- .../models/cosmetic/horns/model.json | 4 ++ 3 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/assets/saturnclient/models/cosmetic/horns/model.json diff --git a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java index ef06149..96daa52 100644 --- a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java @@ -44,11 +44,7 @@ public class HatFeatureRenderer extends FeatureRenderer loadedObjModels = new HashMap<>(); public record Config( - @JsonProperty("transform") Transform transform) { + @JsonProperty("transform") Vec3d transform, + @JsonProperty("scale") Vec3d scale) { @JsonFormat(shape = JsonFormat.Shape.ARRAY) - public record Transform(double x, double y, double z) { + public record Vec3d(float x, float y, float z) { } } @@ -37,21 +45,42 @@ public class ObjModel { } ObjModel(Identifier identifier) { - Identifier obj = Identifier.of(identifier.getNamespace(), identifier.getPath() + ".obj"); - System.out.println(obj); - // Identifier json = Identifier.of(identifier.getNamespace(), identifier.getPath() + ".json"); + Identifier objId = Identifier.of(identifier.getNamespace(), identifier.getPath() + ".obj"); + Identifier jsonId = Identifier.of(identifier.getNamespace(), identifier.getPath() + ".json"); try { - this.obj = ObjRenderer.loadObj(obj); + this.obj = ObjRenderer.loadObj(objId); } catch (IOException e) { e.printStackTrace(); } - Identifier.of(obj.toString()); + // Try loading JSON config if it exists + ResourceManager resourceManager = MinecraftClient.getInstance().getResourceManager(); + Optional resource = resourceManager.getResource(jsonId); + + if (resource.isPresent()) { + try (InputStream stream = resource.get().getInputStream()) { + this.config = MAPPER.readValue(stream, Config.class); + } catch (Exception e) { + e.printStackTrace(); + } + } } public void render(Map mtlMap, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { + matrices.push(); + + matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_X.rotationDegrees(180.0f)); + matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Y.rotationDegrees(180.0f)); + + if (this.config != null) { + matrices.scale(config.scale.x, config.scale.y, config.scale.z); + matrices.translate(config.transform.x, config.transform.y, config.transform.z); + } + ObjRenderer.renderObj(this.obj, mtlMap, matrices, vertexConsumers, light, overlay); + + matrices.pop(); } } diff --git a/src/main/resources/assets/saturnclient/models/cosmetic/horns/model.json b/src/main/resources/assets/saturnclient/models/cosmetic/horns/model.json new file mode 100644 index 0000000..2212050 --- /dev/null +++ b/src/main/resources/assets/saturnclient/models/cosmetic/horns/model.json @@ -0,0 +1,4 @@ +{ + "transform": [0.0, 1.0, 0.0], + "scale": [0.25, 0.25, 0.25] + } \ No newline at end of file From d9e5153452e17fe8f1349317e46b1220344068a3 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 03:54:05 +0100 Subject: [PATCH 13/19] Halo json --- .../assets/saturnclient/models/cosmetic/halo/model.json | 4 ++++ .../assets/saturnclient/models/cosmetic/horns/model.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/assets/saturnclient/models/cosmetic/halo/model.json diff --git a/src/main/resources/assets/saturnclient/models/cosmetic/halo/model.json b/src/main/resources/assets/saturnclient/models/cosmetic/halo/model.json new file mode 100644 index 0000000..1f3c06e --- /dev/null +++ b/src/main/resources/assets/saturnclient/models/cosmetic/halo/model.json @@ -0,0 +1,4 @@ +{ + "transform": [0.0, 3.0, 0.0], + "scale": [0.25, 0.25, 0.25] +} \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/models/cosmetic/horns/model.json b/src/main/resources/assets/saturnclient/models/cosmetic/horns/model.json index 2212050..9554165 100644 --- a/src/main/resources/assets/saturnclient/models/cosmetic/horns/model.json +++ b/src/main/resources/assets/saturnclient/models/cosmetic/horns/model.json @@ -1,4 +1,4 @@ { "transform": [0.0, 1.0, 0.0], "scale": [0.25, 0.25, 0.25] - } \ No newline at end of file +} \ No newline at end of file From 5b9807c5d33908a505363a3d25303f63386f767c Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 04:05:14 +0100 Subject: [PATCH 14/19] Mtl loader --- .../cosmetics/hat/HatFeatureRenderer.java | 16 +----- .../saturnclient/cosmetics/obj/MtlLoader.java | 54 +++++++++++++++++++ .../cosmetics/obj/ObjRenderer.java | 13 ----- 3 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 src/main/java/org/saturnclient/cosmetics/obj/MtlLoader.java diff --git a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java index 96daa52..5f9d4ec 100644 --- a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java @@ -1,13 +1,9 @@ package org.saturnclient.cosmetics.hat; -import java.io.IOException; -import java.util.Map; - +import org.saturnclient.cosmetics.obj.MtlLoader; import org.saturnclient.cosmetics.obj.ObjModel; -import org.saturnclient.cosmetics.obj.ObjRenderer; import org.saturnclient.saturnclient.client.player.SaturnPlayer; -import de.javagl.obj.Mtl; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.feature.FeatureRenderer; @@ -19,16 +15,8 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; public class HatFeatureRenderer extends FeatureRenderer { - static Identifier BLACK_MTL = Identifier.of("saturnclient", "models/cosmetic/black.mtl"); - Map mtl; - public HatFeatureRenderer(FeatureRendererContext context) { super(context); - try { - this.mtl = ObjRenderer.loadMtl(BLACK_MTL); - } catch (IOException e) { - e.printStackTrace(); - } } @Override @@ -46,7 +34,7 @@ public class HatFeatureRenderer extends FeatureRenderer> loadedMtls = new HashMap<>(); + + static Map loadMtl(Identifier mtlId) throws IOException { + try (InputStream is = MinecraftClient.getInstance().getResourceManager() + .getResource(mtlId).get().getInputStream()) { + List mtlList = MtlReader.read(is); + Map mtlMap = new java.util.LinkedHashMap<>(); + for (Mtl mtl : mtlList) { + mtlMap.put(mtl.getName(), mtl); + } + return mtlMap; + } + } + + public static Map of(Identifier mtlId) { + if (loadedMtls.containsKey(mtlId)) + return loadedMtls.get(mtlId); + + try { + Map mtl = loadMtl(mtlId); + loadedMtls.put(mtlId, mtl); + + return mtl; + } catch (IOException e) { + e.printStackTrace(); + + return null; + } + + } + + public static Map cosmetic(String cosmeticId) { + String input = "halo_black"; + int index = input.indexOf('_'); + + String mtlId = (index == -1) ? "" : input.substring(index + 1); + + return of(Identifier.of("saturnclient", "models/cosmetic/" + mtlId + ".mtl")); + } +} diff --git a/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java b/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java index 6f59fe6..498e4f0 100644 --- a/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/obj/ObjRenderer.java @@ -2,7 +2,6 @@ package org.saturnclient.cosmetics.obj; import java.io.IOException; import java.io.InputStream; -import java.util.List; import java.util.Map; import de.javagl.obj.*; @@ -22,18 +21,6 @@ public class ObjRenderer { } } - public static Map loadMtl(Identifier mtlId) throws IOException { - try (InputStream is = MinecraftClient.getInstance().getResourceManager() - .getResource(mtlId).get().getInputStream()) { - List mtlList = MtlReader.read(is); - Map mtlMap = new java.util.LinkedHashMap<>(); - for (Mtl mtl : mtlList) { - mtlMap.put(mtl.getName(), mtl); - } - return mtlMap; - } - } - public static void renderObj(Obj obj, Map mtlMap, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { MatrixStack.Entry entry = matrices.peek(); From 8ed855723bf5f7cf6e6c8ab144a91f830aa96763 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 04:10:19 +0100 Subject: [PATCH 15/19] Working cosmetic id mtl loader --- .../java/org/saturnclient/cosmetics/obj/MtlLoader.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/saturnclient/cosmetics/obj/MtlLoader.java b/src/main/java/org/saturnclient/cosmetics/obj/MtlLoader.java index cbc31f1..b4a8426 100644 --- a/src/main/java/org/saturnclient/cosmetics/obj/MtlLoader.java +++ b/src/main/java/org/saturnclient/cosmetics/obj/MtlLoader.java @@ -27,6 +27,7 @@ public class MtlLoader { } public static Map of(Identifier mtlId) { + System.out.println(mtlId); if (loadedMtls.containsKey(mtlId)) return loadedMtls.get(mtlId); @@ -44,10 +45,12 @@ public class MtlLoader { } public static Map cosmetic(String cosmeticId) { - String input = "halo_black"; - int index = input.indexOf('_'); + int index = cosmeticId.indexOf('_'); - String mtlId = (index == -1) ? "" : input.substring(index + 1); + String mtlId = (index == -1) ? "" : cosmeticId.substring(index + 1); + + if (mtlId.isEmpty()) + mtlId = "white"; return of(Identifier.of("saturnclient", "models/cosmetic/" + mtlId + ".mtl")); } From 944bada2a241d69984287ed1a5a16a83ae6efc2e Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 09:53:12 +0100 Subject: [PATCH 16/19] Refactored structure --- .../cosmetics/hat/HatFeatureRenderer.java | 11 ++++------- .../org/saturnclient/cosmetics/obj/MtlLoader.java | 2 +- .../java/org/saturnclient/cosmetics/obj/ObjModel.java | 4 ++++ .../models/cosmetic/{ => hat}/halo/model.json | 0 .../models/cosmetic/{ => hat}/halo/model.obj | 0 .../models/cosmetic/{ => hat}/horns/model.json | 0 .../models/cosmetic/{ => hat}/horns/model.obj | 0 .../models/cosmetic/{ => materials}/black.mtl | 0 .../models/cosmetic/{ => materials}/white.mtl | 0 9 files changed, 9 insertions(+), 8 deletions(-) rename src/main/resources/assets/saturnclient/models/cosmetic/{ => hat}/halo/model.json (100%) rename src/main/resources/assets/saturnclient/models/cosmetic/{ => hat}/halo/model.obj (100%) rename src/main/resources/assets/saturnclient/models/cosmetic/{ => hat}/horns/model.json (100%) rename src/main/resources/assets/saturnclient/models/cosmetic/{ => hat}/horns/model.obj (100%) rename src/main/resources/assets/saturnclient/models/cosmetic/{ => materials}/black.mtl (100%) rename src/main/resources/assets/saturnclient/models/cosmetic/{ => materials}/white.mtl (100%) diff --git a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java index 5f9d4ec..98b536e 100644 --- a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java @@ -11,8 +11,6 @@ import net.minecraft.client.render.entity.feature.FeatureRendererContext; import net.minecraft.client.render.entity.model.PlayerEntityModel; import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; public class HatFeatureRenderer extends FeatureRenderer { public HatFeatureRenderer(FeatureRendererContext context) { @@ -22,10 +20,9 @@ public class HatFeatureRenderer extends FeatureRenderer Date: Tue, 3 Mar 2026 10:00:58 +0100 Subject: [PATCH 17/19] Refactored json --- src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java | 4 ++-- .../assets/saturnclient/models/cosmetic/hat/halo/model.json | 4 ++-- .../assets/saturnclient/models/cosmetic/hat/horns/model.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java b/src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java index 6cf3323..f1e69bc 100644 --- a/src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java +++ b/src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java @@ -24,7 +24,7 @@ public class ObjModel { public static final Map loadedObjModels = new HashMap<>(); public record Config( - @JsonProperty("transform") Vec3d transform, + @JsonProperty("translate") Vec3d transform, @JsonProperty("scale") Vec3d scale) { @JsonFormat(shape = JsonFormat.Shape.ARRAY) @@ -79,8 +79,8 @@ public class ObjModel { matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Y.rotationDegrees(180.0f)); if (this.config != null) { - matrices.scale(config.scale.x, config.scale.y, config.scale.z); matrices.translate(config.transform.x, config.transform.y, config.transform.z); + matrices.scale(config.scale.x, config.scale.y, config.scale.z); } ObjRenderer.renderObj(this.obj, mtlMap, matrices, vertexConsumers, light, overlay); diff --git a/src/main/resources/assets/saturnclient/models/cosmetic/hat/halo/model.json b/src/main/resources/assets/saturnclient/models/cosmetic/hat/halo/model.json index 1f3c06e..e1f2835 100644 --- a/src/main/resources/assets/saturnclient/models/cosmetic/hat/halo/model.json +++ b/src/main/resources/assets/saturnclient/models/cosmetic/hat/halo/model.json @@ -1,4 +1,4 @@ { - "transform": [0.0, 3.0, 0.0], - "scale": [0.25, 0.25, 0.25] + "translate": [0.0, 0.62, 0.0], + "scale": [0.2, 0.1, 0.2] } \ No newline at end of file diff --git a/src/main/resources/assets/saturnclient/models/cosmetic/hat/horns/model.json b/src/main/resources/assets/saturnclient/models/cosmetic/hat/horns/model.json index 9554165..1387e00 100644 --- a/src/main/resources/assets/saturnclient/models/cosmetic/hat/horns/model.json +++ b/src/main/resources/assets/saturnclient/models/cosmetic/hat/horns/model.json @@ -1,4 +1,4 @@ { - "transform": [0.0, 1.0, 0.0], + "translate": [0.0, 0.25, 0.0], "scale": [0.25, 0.25, 0.25] } \ No newline at end of file From 8be1bab1b68f5b0b1c33945b164faf93f0ad38ee Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 11:28:34 +0100 Subject: [PATCH 18/19] Rotation --- .../org/saturnclient/cosmetics/obj/ObjModel.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java b/src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java index f1e69bc..bfe2ac1 100644 --- a/src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java +++ b/src/main/java/org/saturnclient/cosmetics/obj/ObjModel.java @@ -25,7 +25,14 @@ public class ObjModel { public record Config( @JsonProperty("translate") Vec3d transform, - @JsonProperty("scale") Vec3d scale) { + @JsonProperty("scale") Vec3d scale, + @JsonProperty("rotation") Vec3d rotation) { + + public Config { + transform = transform == null ? new Vec3d(0, 0, 0) : transform; + scale = scale == null ? new Vec3d(1, 1, 1) : scale; + rotation = rotation == null ? new Vec3d(0, 0, 0) : rotation; + } @JsonFormat(shape = JsonFormat.Shape.ARRAY) public record Vec3d(float x, float y, float z) { @@ -80,7 +87,12 @@ public class ObjModel { if (this.config != null) { matrices.translate(config.transform.x, config.transform.y, config.transform.z); + matrices.scale(config.scale.x, config.scale.y, config.scale.z); + + matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_X.rotationDegrees(config.rotation.x)); + matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Y.rotationDegrees(config.rotation.y)); + matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(config.rotation.z)); } ObjRenderer.renderObj(this.obj, mtlMap, matrices, vertexConsumers, light, overlay); From 6ad563fd4a737364f94ead7155cba2dfe1ebac8d Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 3 Mar 2026 11:32:02 +0100 Subject: [PATCH 19/19] Removed old obj library --- build.gradle | 16 +++++----------- .../saturnclient/saturnclient/SaturnClient.java | 6 ------ 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/build.gradle b/build.gradle index 0a1aa1f..dac203e 100644 --- a/build.gradle +++ b/build.gradle @@ -47,11 +47,8 @@ repositories { // 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/' } + maven { name = "KoSmX Maven"; url = 'https://maven.kosmx.dev/' } // Central repository mavenCentral() @@ -83,10 +80,7 @@ dependencies { // 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" - + // OBJ Reading Library implementation "de.javagl:obj:0.4.0" include "de.javagl:obj:0.4.0" @@ -98,12 +92,12 @@ dependencies { // Animation // ───────────────────────────────────────────── - // Player Animation Library (bundled into your mod) + // Player Animation Library include modImplementation( "dev.kosmx.player-anim:player-animation-lib-fabric:${project.player_anim}" ) - // Optional: BendyLib (only if you directly use it) + // Optional: BendyLib // include modRuntimeOnly( // "io.github.kosmx.bendy-lib:bendy-lib-fabric:${project.bendylib_version}" // ) @@ -113,7 +107,7 @@ dependencies { // External Libraries // ───────────────────────────────────────────── - // Session Java (auth/session handling) + // Session Java (Saturn auth/session handling) include implementation("com.github.selimaj-dev:session-java:0.1.6") } diff --git a/src/main/java/org/saturnclient/saturnclient/SaturnClient.java b/src/main/java/org/saturnclient/saturnclient/SaturnClient.java index 9d2db7f..ba767c9 100644 --- a/src/main/java/org/saturnclient/saturnclient/SaturnClient.java +++ b/src/main/java/org/saturnclient/saturnclient/SaturnClient.java @@ -23,8 +23,6 @@ import org.saturnclient.ui2.screens.TitleMenu; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import dev.felnull.specialmodelloader.api.event.SpecialModelLoaderEvents; - /** * Main class for the Saturn Client mod. */ @@ -47,10 +45,6 @@ public class SaturnClient implements ModInitializer { ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> ConfigManager.save()); - SpecialModelLoaderEvents.LOAD_SCOPE.register(() -> { - return (resourceManager, location) -> MOD_ID.equals(location.getNamespace()); - }); - ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { if (screen != null && !(screen instanceof TitleMenu)) { if (screen instanceof SaturnScreen) {