Hide the cloak on torso-curving emotes and point common at #12 #45

Merged
selimaj-dev merged 2 commits from release-fixes into master 2026-09-29 16:35:28 +00:00
2 changed files with 34 additions and 4 deletions
+1 -1
Submodule common updated: 6d5df3057e...b0d75af8c4
@@ -1,6 +1,9 @@
package org.saturnclient.impl.cosmetics; package org.saturnclient.impl.cosmetics;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import org.joml.Matrix3f; import org.joml.Matrix3f;
import org.joml.Matrix4f; import org.joml.Matrix4f;
@@ -11,6 +14,8 @@ import org.saturnclient.client.player.SaturnPlayer;
import org.saturnclient.common.ref.asset.IdentifierRef; import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.config.Config; import org.saturnclient.config.Config;
import org.saturnclient.cosmetics.Cloaks; 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.LimbBend;
import org.saturnclient.emotes.core.bend.Vec3; import org.saturnclient.emotes.core.bend.Vec3;
import org.saturnclient.emotes.fabric.access.BendablePart; import org.saturnclient.emotes.fabric.access.BendablePart;
@@ -387,9 +392,34 @@ 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<>());
/** /**
* An emote that bends the torso leans the chest from the hips, so the cloak hangs from where the * Whether the player is playing an emote that curves the torso (a twerk, the griddy). The cloak
* top of the back ends up, turned as much as the torso is there. * 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) { private static void followBend(MatrixStack matrices, ModelPart body) {
LimbBend bend = ((BendablePart) (Object) body).saturnEmotes$getBend(); LimbBend bend = ((BendablePart) (Object) body).saturnEmotes$getBend();
@@ -439,7 +469,7 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
//?} else //?} else
//SaturnPlayer player = SaturnPlayer.get(state.name); //SaturnPlayer player = SaturnPlayer.get(state.name);
if (player == null) { if (player == null || playingTorsoBend(player)) {
return; return;
} }