From 45f8c655493d96bebdde832d1313dc90ff6daf34 Mon Sep 17 00:00:00 2001 From: Kleo Dev Date: Thu, 4 Sep 2025 19:54:35 +0200 Subject: [PATCH] Bendy cloak option and slight cloak jiggle --- .../saturnclient/SaturnClientConfig.java | 5 +- .../cosmetics/CloakFeatureRenderer.java | 189 ++++++++++-------- .../mixin/PlayerEntityRendererMixin.java | 2 +- 3 files changed, 113 insertions(+), 83 deletions(-) diff --git a/src/main/java/org/saturnclient/saturnclient/SaturnClientConfig.java b/src/main/java/org/saturnclient/saturnclient/SaturnClientConfig.java index adf7737..db45255 100644 --- a/src/main/java/org/saturnclient/saturnclient/SaturnClientConfig.java +++ b/src/main/java/org/saturnclient/saturnclient/SaturnClientConfig.java @@ -12,8 +12,8 @@ public class SaturnClientConfig { public static ConfigManager config; public static Property realisticLogo = Property.bool(false); - public static Property saturnTitleScreen = Property.bool(true); + public static Property bendyCloaks = Property.bool(true); public static Property openEmoteWheel = Property.keybinding(GLFW.GLFW_KEY_B); public static Identifier getLogo() { @@ -32,7 +32,7 @@ public class SaturnClientConfig { * - Partners: Gold * - Contributor: Aqua * - Other/player: White - */ + */ public static Formatting getIconColor(String uuid) { if (uuid.equals("d362a04228bd49e1a807ae74dbe8aba9")) { return Formatting.DARK_RED; // Owner @@ -46,5 +46,6 @@ public class SaturnClientConfig { config.property("Realistic logo", realisticLogo); config.property("Saturn client title screen", saturnTitleScreen); config.property("Open Emote Wheel", openEmoteWheel); + config.property("Bendy Cloaks", bendyCloaks); } } diff --git a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java index d687687..4ea4365 100644 --- a/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java +++ b/src/main/java/org/saturnclient/saturnclient/cosmetics/CloakFeatureRenderer.java @@ -1,5 +1,6 @@ package org.saturnclient.saturnclient.cosmetics; +import org.saturnclient.saturnclient.SaturnClientConfig; import org.saturnclient.saturnclient.auth.Auth; import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; @@ -12,9 +13,12 @@ import net.minecraft.client.render.entity.equipment.EquipmentModelLoader; import net.minecraft.client.render.entity.equipment.EquipmentModel.LayerType; import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.render.entity.feature.FeatureRendererContext; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.client.render.entity.model.EntityModelLayers; +import net.minecraft.client.render.entity.model.LoadedEntityModels; +import net.minecraft.client.render.entity.model.PlayerCapeModel; import net.minecraft.client.render.entity.model.PlayerEntityModel; import net.minecraft.client.render.entity.state.PlayerEntityRenderState; -import net.minecraft.client.util.SkinTextures; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.EquippableComponent; @@ -27,17 +31,22 @@ import net.minecraft.util.math.Vec3d; public class CloakFeatureRenderer extends FeatureRenderer { private final EquipmentModelLoader equipmentModelLoader; + private final BipedEntityModel model; private static final int PARTS = 16; private float currentVelocity = 0.0f; public CloakFeatureRenderer(FeatureRendererContext context, + LoadedEntityModels modelLoader, EquipmentModelLoader equipmentModelLoader) { super(context); + this.model = new PlayerCapeModel( + modelLoader.getModelPart(EntityModelLayers.PLAYER_CAPE)); this.equipmentModelLoader = equipmentModelLoader; } private boolean hasCustomModelForLayer(ItemStack stack, EquipmentModel.LayerType layerType) { - EquippableComponent equippableComponent = (EquippableComponent) stack.get(DataComponentTypes.EQUIPPABLE); + EquippableComponent equippableComponent = (EquippableComponent) stack + .get(DataComponentTypes.EQUIPPABLE); if (equippableComponent != null && !equippableComponent.assetId().isEmpty()) { EquipmentModel equipmentModel = this.equipmentModelLoader .get((RegistryKey) equippableComponent.assetId().get()); @@ -47,24 +56,6 @@ public class CloakFeatureRenderer extends FeatureRenderer> 4) & 0xF; - int skyLight = (light >> 20) & 0xF; - blockLight = Math.max(blockLight, minBrightness); - skyLight = Math.max(skyLight, minBrightness); - light = (skyLight << 20) | (blockLight << 4); - - matrixStack.push(); - matrixStack.translate(0.0f, -0.25f, 0.0f); - if (this.hasCustomModelForLayer(playerEntityRenderState.equippedChestStack, LayerType.HUMANOID)) { - matrixStack.translate(0.0F, -0.053125F, 0.06875F); - } - VertexConsumer vertexConsumer = vertexConsumerProvider - .getBuffer(RenderLayer.getEntityAlpha(customCape)); - renderCape(matrixStack, vertexConsumer, playerEntityRenderState, light, OverlayTexture.DEFAULT_UV, - Math.min(rotation, 70.0f), Math.min(curve, 0.46f)); - matrixStack.pop(); - } - } + if (playerEntityRenderState.invisible || !playerEntityRenderState.capeVisible) { + return; } + + if (playerEntityRenderState.skinTextures.capeTexture() != null) { + return; + } + String name = playerEntityRenderState.name; + String uuid = Auth.playerNames.get(name); + if (uuid == null || !Auth.players.containsKey(uuid)) { + return; + } + + Identifier customCape = Cloaks.getCurrentCloakTexture(uuid); + if (customCape == null + || this.hasCustomModelForLayer( + playerEntityRenderState.equippedChestStack, + LayerType.WINGS)) { + return; + } + + int minBrightness = 7; + int blockLight = (light >> 4) & 0xF; + int skyLight = (light >> 20) & 0xF; + blockLight = Math.max(blockLight, minBrightness); + skyLight = Math.max(skyLight, minBrightness); + light = (skyLight << 20) | (blockLight << 4); + + matrixStack.push(); + + VertexConsumer vertexConsumer = vertexConsumerProvider + .getBuffer(RenderLayer.getEntityAlpha(customCape)); + + if (this.hasCustomModelForLayer(playerEntityRenderState.equippedChestStack, + LayerType.HUMANOID)) { + matrixStack.translate(0.0F, -0.053125F, 0.06875F); + } + + if (SaturnClientConfig.bendyCloaks.value) { + float targetVelocity = ((6.0F + + playerEntityRenderState.field_53537 / 2.0F + + playerEntityRenderState.field_53536) * 0.02f); + targetVelocity = Math.max(0.0f, targetVelocity - 0.1f); + + float accelerationRate = 0.02f; + this.currentVelocity = this.currentVelocity + + (targetVelocity - this.currentVelocity) + * accelerationRate; + + float rotation = this.currentVelocity * 72.0f; + float curve = this.currentVelocity * 0.4f; + + matrixStack.translate(0.0f, -0.25f, 0.0f); + if (this.hasCustomModelForLayer( + playerEntityRenderState.equippedChestStack, + LayerType.HUMANOID)) { + matrixStack.translate(0.0F, -0.053125F, 0.06875F); + } + + renderCape(matrixStack, vertexConsumer, playerEntityRenderState, light, + OverlayTexture.DEFAULT_UV, + Math.min(rotation, 60.0f), Math.min(curve, 0.5f)); + } else { + ((PlayerEntityModel) this.getContextModel()).copyTransforms(this.model); + this.model.setAngles(playerEntityRenderState); + this.model.render(matrixStack, vertexConsumer, light, OverlayTexture.DEFAULT_UV); + } + + matrixStack.pop(); } } \ No newline at end of file diff --git a/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java b/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java index 9726b3e..8a90739 100644 --- a/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java +++ b/src/main/java/org/saturnclient/saturnclient/mixin/PlayerEntityRendererMixin.java @@ -25,6 +25,6 @@ public abstract class PlayerEntityRendererMixin @Inject(method = "", at = @At("TAIL")) private void addCustomFeatureRenderer(EntityRendererFactory.Context ctx, boolean slim, CallbackInfo ci) { this.addFeature(new HatFeatureRenderer(this)); - this.addFeature(new CloakFeatureRenderer(this, ctx.getEquipmentModelLoader())); + this.addFeature(new CloakFeatureRenderer(this, ctx.getEntityModels(), ctx.getEquipmentModelLoader())); } } \ No newline at end of file