Compare commits

...
15 Commits
Author SHA1 Message Date
selimaj-dev 37db94649f Merge pull request 'Bump the version to 0.1.4-beta' (#46) from release-0.1.4-beta into master
Release / build (release) Successful in 4m36s
Reviewed-on: #46
2026-09-29 16:37:19 +00:00
selimaj-devandclaude 896f4cccc0 Bump the version to 0.1.4-beta
Check / compile (pull_request) Successful in 2m29s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 18:37:03 +02:00
selimaj-dev de3c554e63 Merge pull request 'Hide the cloak on torso-curving emotes and point common at #12' (#45) from release-fixes into master
Reviewed-on: #45
2026-09-29 16:35:28 +00:00
selimaj-devandclaude 8417427059 Point common at the None cloak fix and the sidebar and dock order
Check / compile (pull_request) Successful in 2m29s
Picks up common#12.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 18:35:14 +02:00
selimaj-devandclaude ba5a32fb34 Hide the cloak during emotes that curve the torso
A flat cloak can't follow an arched back, so on the twerk it cut through the player. When the
emote being played bends the torso more than 10 degrees at any point, the cloak is hidden for the
whole emote; hiding it only while the back is curved would make it flicker. Each emote is checked
once and cached. Emotes that bend the torso less still hang the cloak from the leaning chest.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 18:34:34 +02:00
selimaj-dev 8b1c94151a Merge pull request 'Use emotes 0.1.1 and point common at the new emotes' (#44) from new-emotes into master
Reviewed-on: #44
2026-09-29 16:03:15 +00:00
selimaj-devandclaude 3623024cce Use emotes 0.1.1 and point common at the new emotes
Check / compile (pull_request) Successful in 2m30s
Emotes 0.1.1 bends the torso the right way round. common now has seven more emotes and a twerk
re-exported for that fix (common#11), so the two move together.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 18:02:50 +02:00
selimaj-dev 2dcbe0302e Merge pull request 'Point common at the twerk emote' (#43) from twerk-emote into master
Reviewed-on: #43
2026-09-29 15:04:46 +00:00
selimaj-devandclaude 502bddd720 Point common at the twerk emote
Check / compile (pull_request) Successful in 2m39s
Picks up the twerk emote and the removal of the front flip (common#10).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 17:01:52 +02:00
selimaj-devandclaude 0c22fee8c0 Point common at the opaque theme upgrade
Release / build (release) Successful in 5m26s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 23:12:35 +02:00
selimaj-dev f69f6eb883 Merge pull request 'Bump the version to 0.1.3-beta' (#42) from release-0.1.3-beta into master
Reviewed-on: #42
2026-09-28 21:02:25 +00:00
selimaj-devandclaude cebd9aec96 Bump the version to 0.1.3-beta
Check / compile (pull_request) Successful in 3m0s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 23:02:09 +02:00
selimaj-dev 2554a84950 Merge pull request 'Keep hats and cloaks on the posed model, and fix resources on 1.21.4 and 1.21.5' (#41) from cosmetics-follow-emotes into master
Reviewed-on: #41
2026-09-28 21:01:06 +00:00
selimaj-devandclaude 49bbdff418 Keep hats and cloaks on the posed head and body
Check / compile (pull_request) Successful in 2m57s
The hat only took the head's rotation from 1.21.5, and the cloak sat at
a fixed spot with a hard-coded crouch, so crouching and emotes left them
where the head and body had been. Both now follow the whole player (the
root, which emotes like the backflip turn) and then the head or body, as
vanilla places head items, and the cloak leans with the chest when an
emote bends the torso.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 23:00:40 +02:00
selimaj-devandclaude 8995de9067 Stop the glass shader importing what older versions lack
1.21.4 and 1.21.5 read every shader's imports while loading resources,
and dynamictransforms.glsl only exists from 1.21.6, so resources failed
to load there. The glass shader declares the transforms block itself
again, with LineWidth behind a define the pipeline sets before 1.21.11.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 23:00:40 +02:00
6 changed files with 94 additions and 18 deletions
+1 -1
Submodule common updated: 7d0bfd26c9...b0d75af8c4
+2 -2
View File
@@ -6,10 +6,10 @@ org.gradle.caching=true
# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349
org.gradle.configuration-cache=false
mod_version=0.1.2-beta
mod_version=0.1.4-beta
# Saturn's emote library (git.selimaj.dev/saturnclientmc/emotes)
emotes_version=0.1.0
emotes_version=0.1.1
# Loom, for every Minecraft version (read in settings.gradle.kts).
loom_version=1.17.21
@@ -1,18 +1,28 @@
package org.saturnclient.impl.cosmetics;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.joml.Vector4f;
import org.saturnclient.client.player.SaturnPlayer;
import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.config.Config;
import org.saturnclient.cosmetics.Cloaks;
import org.saturnclient.emotes.core.Animation;
import org.saturnclient.emotes.core.Bone;
import org.saturnclient.emotes.core.bend.LimbBend;
import org.saturnclient.emotes.core.bend.Vec3;
import org.saturnclient.emotes.fabric.access.BendablePart;
import org.saturnclient.impl.cosmetics.utils.ShaderUtils;
import org.saturnclient.saturnclient.SaturnRenderState;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumer;
//? if >=1.21.9 {
@@ -33,7 +43,6 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.equipment.EquipmentAsset;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.math.Vec3d;
/**
@@ -383,6 +392,50 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
}
}
/** A torso bend past this curves the back more than a flat cloak can follow. */
private static final float MAX_CLOAK_BEND = (float) Math.toRadians(10);
/** Whether each animation bends the torso past that at any point. */
private static final Map<Animation, Boolean> BENDS_TORSO = Collections.synchronizedMap(new WeakHashMap<>());
/**
* Whether the player is playing an emote that curves the torso (a twerk, the griddy). The cloak
* would cut through the arched back, so it's hidden for the whole emote rather than only while
* the back is curved, which would flicker.
*/
private static boolean playingTorsoBend(SaturnPlayer player) {
return org.saturnclient.emotes.fabric.Emotes.playing(player.uuid)
.map(playing -> BENDS_TORSO.computeIfAbsent(playing.animation(), CloakFeatureRenderer::bendsTorso))
.orElse(false);
}
private static boolean bendsTorso(Animation animation) {
for (float tick = 0; tick <= animation.length(); tick += 0.5f) {
if (animation.sample(tick).get(Bone.BODY).filter(body -> Math.abs(body.bend()) > MAX_CLOAK_BEND).isPresent()) {
return true;
}
}
return false;
}
/**
* An emote that bends the torso a little leans the chest from the hips, so the cloak hangs from
* where the top of the back ends up, turned as much as the torso is there.
*/
private static void followBend(MatrixStack matrices, ModelPart body) {
LimbBend bend = ((BendablePart) (Object) body).saturnEmotes$getBend();
if (bend == null || bend.isStraight()) {
return;
}
// The top of the torso, in the body's own pixels
float[] top = new float[3];
bend.bendPoint(0, 0, 0, top);
matrices.translate(top[0] / 16.0f, top[1] / 16.0f, top[2] / 16.0f);
Vec3 axis = bend.axis();
matrices.multiply(new Quaternionf().rotationAxis(bend.angleAt(0), axis.x(), axis.y(), axis.z()));
}
// Shift array left and insert new value at the start
private void updateSegmentValues(float value) {
// Shift all elements one position to the right (from end to start)
@@ -416,7 +469,7 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
//?} else
//SaturnPlayer player = SaturnPlayer.get(state.name);
if (player == null) {
if (player == null || playingTorsoBend(player)) {
return;
}
@@ -436,17 +489,24 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
matrices.push();
// On the back: the whole player (which emotes like the backflip turn), then the body's position
// and turn (which crouching and emotes move), then the chest's lean when an emote bends the torso
PlayerEntityModel model = this.getContextModel();
//? if >=1.21.5 {
model.getRootPart().applyTransform(matrices);
model.body.applyTransform(matrices);
//?} else {
/*model.getRootPart().rotate(matrices);
model.body.rotate(matrices);
*///?}
followBend(matrices, model.body);
matrices.translate(0.0f, 0.0f, 0.12f);
if (this.hasCustomModelForLayer(state.equippedChestStack, LayerType.HUMANOID)) {
matrices.translate(0.0F, -0.053125F, 0.06875F);
}
if (state.isInSneakingPose) {
matrices.translate(0, 0.16f, 0.0f);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(29.0f));
}
long now = System.currentTimeMillis();
if (now - lastUpdate >= 20) {
float velX = Math.min(0.8f, state.field_53537 / 108.0f);
@@ -1,6 +1,5 @@
package org.saturnclient.impl.cosmetics;
import org.joml.Quaternionf;
import org.saturnclient.client.player.SaturnPlayer;
import org.saturnclient.impl.cosmetics.obj.MtlLoader;
import org.saturnclient.impl.cosmetics.obj.ObjModel;
@@ -16,7 +15,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.client.model.ModelPart;
public class HatFeatureRenderer extends FeatureRenderer<PlayerEntityRenderState, PlayerEntityModel> {
public HatFeatureRenderer(FeatureRendererContext<PlayerEntityRenderState, PlayerEntityModel> context) {
@@ -41,11 +39,16 @@ public class HatFeatureRenderer extends FeatureRenderer<PlayerEntityRenderState,
matrices.push();
// On the head, as vanilla places head items: the whole player (which emotes like the backflip
// turn), then the head's position, turn and scale (which crouching and emotes move)
PlayerEntityModel model = this.getContextModel();
//? if >=1.21.5 {
ModelPart head = this.getContextModel().head;
matrices.multiply(new Quaternionf().rotationZYX(head.roll, head.yaw, head.pitch));
//?} else
//this.getContextModel().head.rotate(matrices);
model.getRootPart().applyTransform(matrices);
model.head.applyTransform(matrices);
//?} else {
/*model.getRootPart().rotate(matrices);
model.head.rotate(matrices);
*///?}
ObjModel.cosmetic("hat", player.hat).render(MtlLoader.cosmetic(player.hat),
matrices, output, light,
@@ -48,6 +48,9 @@ public final class GlassRenderer {
.withLocation(Identifier.of("saturnclient", "pipeline/glass"))
.withFragmentShader(Identifier.of("saturnclient", "core/glass"))
.withSampler("Sampler1")
// The transforms block ends with LineWidth before 1.21.11 (see glass.fsh).
//? if <1.21.11
//.withShaderDefine("HAS_LINE_WIDTH")
.build();
private static final Identifier BLUR = Identifier.ofVanilla("post_effect/blur.json");
@@ -3,8 +3,18 @@
// Saturn's glass: the blurred game behind the screen, cut to a panel's shape. For 1.21.6 and
// later; glass_pre_1_21_6.fsh (with glass.json, the program 1.21.4 loads) is for older versions.
// Vanilla's own, since its layout changes between versions (1.21.11 dropped LineWidth)
#moj_import <minecraft:dynamictransforms.glsl>
// Vanilla's transforms, laid out as the version has them: 1.21.6 to 1.21.10 end with LineWidth, which
// 1.21.11 dropped (GlassRenderer defines HAS_LINE_WIDTH there). Not imported: the include only exists
// from 1.21.6, and 1.21.4 and 1.21.5 still read every shader's imports while loading resources.
layout(std140) uniform DynamicTransforms {
mat4 ModelViewMat;
vec4 ColorModulator;
vec3 ModelOffset;
mat4 TextureMat;
#ifdef HAS_LINE_WIDTH
float LineWidth;
#endif
};
// The panel's rounded rectangle, the same texture its background is drawn with
uniform sampler2D Sampler0;