Compare commits

...
Author SHA1 Message Date
selimaj-dev 920657ddd3 Beta 2 2025-09-08 18:46:29 +02:00
selimaj-dev 32035a2f7d Fixed flat cloak with new optimised textures 2025-09-06 12:07:30 +02:00
Leo Codes c230f4f5ec Merge pull request #7 from saturnclientmc/optimised-cloak
Optimised cloak texture size
2025-09-06 02:24:46 +02:00
selimaj-dev 50d1028e53 Optimised cloak texture size 2025-09-06 02:21:40 +02:00
Leo Codes 780cb9ba9a Merge pull request #6 from saturnclientmc/cloak-edge-cases
Cloak edge cases
2025-09-05 18:05:24 +02:00
selimaj-dev 65df9e9a5e Fixed cloak when crouching #5 2025-09-05 17:49:45 +02:00
selimaj-dev 66f8a13faa Added a wave effect #5 2025-09-05 17:09:46 +02:00
selimaj-dev 1726542c84 Fixed cloak when swimming #5 2025-09-05 16:35:57 +02:00
20 changed files with 179 additions and 166 deletions
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.7
loader_version=0.16.10 loader_version=0.16.10
fabric_version=0.114.0+1.21.4 fabric_version=0.114.0+1.21.4
mod_version = 0.0.5-beta1 mod_version = 0.0.5-beta2
maven_group = org.saturnclient maven_group = org.saturnclient
archives_base_name = saturnclient archives_base_name = saturnclient
@@ -13,10 +13,6 @@ import net.minecraft.client.render.entity.equipment.EquipmentModelLoader;
import net.minecraft.client.render.entity.equipment.EquipmentModel.LayerType; import net.minecraft.client.render.entity.equipment.EquipmentModel.LayerType;
import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.render.entity.feature.FeatureRenderer;
import net.minecraft.client.render.entity.feature.FeatureRendererContext; 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.model.PlayerEntityModel;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
@@ -29,18 +25,58 @@ import net.minecraft.util.Identifier;
import net.minecraft.util.math.RotationAxis; import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
/**
* The cloak renderer
* - **Efficient**: uses a image only consisting of the cloak texture, 16x8
* whitespace.
* - **Curving**: Curves when player velocity increases.
* - **Wavey**: Makes the cloak feel like wind, when jump sprinting.
*/
public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderState, PlayerEntityModel> { public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderState, PlayerEntityModel> {
private final EquipmentModelLoader equipmentModelLoader; private final EquipmentModelLoader equipmentModelLoader;
private final BipedEntityModel<PlayerEntityRenderState> model;
private static final int PARTS = 16; private static final int PARTS = 16;
private float currentVelocity = 0.0f; private float currentVelocity = 0.0f;
private static final float TEX_W = 176f;
private static final float TEX_H = 138f;
private static final class PxRect {
final int x, y, w, h;
PxRect(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
float u1() {
return x / TEX_W;
}
float v1() {
return y / TEX_H;
}
float u2() {
return (x + w) / TEX_W;
}
float v2() {
return (y + h) / TEX_H;
}
}
private static final PxRect FRONT_RECT = new PxRect(8, 8, 80, 128);
private static final PxRect BACK_RECT = new PxRect(96, 8, 80, 128);
private static final PxRect LEFT_EDGE_RECT = new PxRect(0, 8, 8, 128);
private static final PxRect RIGHT_EDGE_RECT = new PxRect(88, 8, 8, 128);
private static final PxRect TOP_RECT = new PxRect(8, 0, 80, 8);
private static final PxRect BOTTOM_RECT = new PxRect(88, 0, 80, 8);
public CloakFeatureRenderer(FeatureRendererContext<PlayerEntityRenderState, PlayerEntityModel> context, public CloakFeatureRenderer(FeatureRendererContext<PlayerEntityRenderState, PlayerEntityModel> context,
LoadedEntityModels modelLoader,
EquipmentModelLoader equipmentModelLoader) { EquipmentModelLoader equipmentModelLoader) {
super(context); super(context);
this.model = new PlayerCapeModel<PlayerEntityRenderState>(
modelLoader.getModelPart(EntityModelLayers.PLAYER_CAPE));
this.equipmentModelLoader = equipmentModelLoader; this.equipmentModelLoader = equipmentModelLoader;
} }
@@ -63,97 +99,65 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
MatrixStack.Entry entry = matrixStack.peek(); MatrixStack.Entry entry = matrixStack.peek();
if (!flipWinding) { if (!flipWinding) {
// Counter-clockwise winding (front face) // CCW
// Vertex 1 (bottom-left) vertexConsumer.vertex(entry.getPositionMatrix(), (float) bottomLeft.x, (float) bottomLeft.y,
vertexConsumer
.vertex(entry.getPositionMatrix(), (float) bottomLeft.x, (float) bottomLeft.y,
(float) bottomLeft.z) (float) bottomLeft.z)
.color(255, 255, 255, 255) .color(255, 255, 255, 255).texture(u1, v2).overlay(overlay).light(light)
.texture(u1, v2)
.overlay(overlay)
.light(light)
.normal(normalX, normalY, normalZ); .normal(normalX, normalY, normalZ);
vertexConsumer.vertex(entry.getPositionMatrix(), (float) bottomRight.x, (float) bottomRight.y,
// Vertex 2 (bottom-right)
vertexConsumer
.vertex(entry.getPositionMatrix(), (float) bottomRight.x, (float) bottomRight.y,
(float) bottomRight.z) (float) bottomRight.z)
.color(255, 255, 255, 255) .color(255, 255, 255, 255).texture(u2, v2).overlay(overlay).light(light)
.texture(u2, v2)
.overlay(overlay)
.light(light)
.normal(normalX, normalY, normalZ); .normal(normalX, normalY, normalZ);
// Vertex 3 (top-right)
vertexConsumer.vertex(entry.getPositionMatrix(), (float) topRight.x, (float) topRight.y, vertexConsumer.vertex(entry.getPositionMatrix(), (float) topRight.x, (float) topRight.y,
(float) topRight.z) (float) topRight.z)
.color(255, 255, 255, 255) .color(255, 255, 255, 255).texture(u2, v1).overlay(overlay).light(light)
.texture(u2, v1)
.overlay(overlay)
.light(light)
.normal(normalX, normalY, normalZ); .normal(normalX, normalY, normalZ);
// Vertex 4 (top-left)
vertexConsumer.vertex(entry.getPositionMatrix(), (float) topLeft.x, (float) topLeft.y, vertexConsumer.vertex(entry.getPositionMatrix(), (float) topLeft.x, (float) topLeft.y,
(float) topLeft.z) (float) topLeft.z)
.color(255, 255, 255, 255) .color(255, 255, 255, 255).texture(u1, v1).overlay(overlay).light(light)
.texture(u1, v1)
.overlay(overlay)
.light(light)
.normal(normalX, normalY, normalZ); .normal(normalX, normalY, normalZ);
} else { } else {
// Clockwise winding (back face) - reverse vertex order // CW
// Vertex 4 (top-left)
vertexConsumer.vertex(entry.getPositionMatrix(), (float) topLeft.x, (float) topLeft.y, vertexConsumer.vertex(entry.getPositionMatrix(), (float) topLeft.x, (float) topLeft.y,
(float) topLeft.z) (float) topLeft.z)
.color(255, 255, 255, 255) .color(255, 255, 255, 255).texture(u1, v1).overlay(overlay).light(light)
.texture(u1, v1)
.overlay(overlay)
.light(light)
.normal(normalX, normalY, normalZ); .normal(normalX, normalY, normalZ);
// Vertex 3 (top-right)
vertexConsumer.vertex(entry.getPositionMatrix(), (float) topRight.x, (float) topRight.y, vertexConsumer.vertex(entry.getPositionMatrix(), (float) topRight.x, (float) topRight.y,
(float) topRight.z) (float) topRight.z)
.color(255, 255, 255, 255) .color(255, 255, 255, 255).texture(u2, v1).overlay(overlay).light(light)
.texture(u2, v1)
.overlay(overlay)
.light(light)
.normal(normalX, normalY, normalZ); .normal(normalX, normalY, normalZ);
vertexConsumer.vertex(entry.getPositionMatrix(), (float) bottomRight.x, (float) bottomRight.y,
// Vertex 2 (bottom-right)
vertexConsumer
.vertex(entry.getPositionMatrix(), (float) bottomRight.x, (float) bottomRight.y,
(float) bottomRight.z) (float) bottomRight.z)
.color(255, 255, 255, 255) .color(255, 255, 255, 255).texture(u2, v2).overlay(overlay).light(light)
.texture(u2, v2)
.overlay(overlay)
.light(light)
.normal(normalX, normalY, normalZ); .normal(normalX, normalY, normalZ);
vertexConsumer.vertex(entry.getPositionMatrix(), (float) bottomLeft.x, (float) bottomLeft.y,
// Vertex 1 (bottom-left)
vertexConsumer
.vertex(entry.getPositionMatrix(), (float) bottomLeft.x, (float) bottomLeft.y,
(float) bottomLeft.z) (float) bottomLeft.z)
.color(255, 255, 255, 255) .color(255, 255, 255, 255).texture(u1, v2).overlay(overlay).light(light)
.texture(u1, v2)
.overlay(overlay)
.light(light)
.normal(normalX, normalY, normalZ); .normal(normalX, normalY, normalZ);
} }
} }
private float getCurve(int i, float curveMagnitude, PlayerEntityRenderState playerState) {
float powCurve = (float) Math.pow((double) (PARTS - i) / PARTS, 2) * curveMagnitude;
float waveFreq = 0.6f;
float phase = (playerState.age + playerState.handSwingProgress) * 0.4f;
float sineAmplitude = 0.02f;
float sineCurve = (float) Math.sin(i * waveFreq + phase) * sineAmplitude;
float t = Math.min(1.0f, Math.max(0.0f, (curveMagnitude - 0.3f) / 0.2f));
t = t * t * (3 - 2 * t);
return (1.0f - t) * powCurve + t * (powCurve + sineCurve);
}
private void renderCape(MatrixStack matrixStack, VertexConsumer vertexConsumer, private void renderCape(MatrixStack matrixStack, VertexConsumer vertexConsumer,
PlayerEntityRenderState playerState, int light, int overlay, float rotation, PlayerEntityRenderState playerState, int light, int overlay,
float curveMagnitude) { float rotation, float curveMagnitude) {
float capeWidth = 10.0f / 16.0f; // 10 pixels wide float capeWidth = 10.0f / 16.0f;
float capeHeight = 16.0f / 16.0f; // 16 pixels tall float capeHeight = 16.0f / 16.0f;
float capeDepth = 1.0f / 16.0f; // 1 pixel deep float capeDepth = 1.0f / 16.0f;
float capePartHeight = capeHeight / PARTS; float capePartHeight = capeHeight / PARTS;
matrixStack.push(); matrixStack.push();
matrixStack.translate(0.0f, 1.25, 0.125f); matrixStack.translate(0.0f, 1.25, 0.125f);
matrixStack.translate(0, -capeHeight, 0); matrixStack.translate(0, -capeHeight, 0);
matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(rotation)); matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(rotation));
matrixStack.translate(0, capeHeight, 0); matrixStack.translate(0, capeHeight, 0);
@@ -164,101 +168,112 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
float z1 = 0.0f; float z1 = 0.0f;
float z2 = capeDepth; float z2 = capeDepth;
float frontU1 = 1.0f / 64.0f; // Start at pixel 1 final float frontU1 = FRONT_RECT.u1();
float frontU2 = 11.0f / 64.0f; // End at pixel 11 (10 pixels wide) final float frontU2 = FRONT_RECT.u2();
float frontV1 = 1.0f / 32.0f; // Start at pixel 1 final float frontV1 = FRONT_RECT.v1();
float frontV2 = 17.0f / 32.0f; // End at pixel 17 (16 pixels tall) final float frontV2 = FRONT_RECT.v2();
final float frontPartV = (frontV2 - frontV1) / PARTS;
// Back face UV (inside of cape) - typically offset in cape texture final float backU1 = BACK_RECT.u1();
float backU1 = 12.0f / 64.0f; // Back texture starts after front final float backU2 = BACK_RECT.u2();
float backU2 = 22.0f / 64.0f; // 10 pixels wide final float backV1 = BACK_RECT.v1();
float backV2 = 17.0f / 32.0f; final float backV2 = BACK_RECT.v2();
final float backPartV = (backV2 - backV1) / PARTS;
// Top face UV (edge along shoulders) final float leftU1 = LEFT_EDGE_RECT.u1();
float topU1 = 1.0f / 64.0f; // Start at pixel 1 final float leftU2 = LEFT_EDGE_RECT.u2();
float topU2 = 11.0f / 64.0f; // End at pixel 11 final float leftV1 = LEFT_EDGE_RECT.v1();
float topV1 = 0.0f / 32.0f; // Start at pixel 0 final float leftV2 = LEFT_EDGE_RECT.v2();
float topV2 = 1.0f / 32.0f; // End at pixel 1 final float leftPartV = (leftV2 - leftV1) / PARTS;
// Bottom face UV (lower edge of cape) final float rightU1 = RIGHT_EDGE_RECT.u1();
float bottomU1 = 11.0f / 64.0f; // Start at pixel 11 final float rightU2 = RIGHT_EDGE_RECT.u2();
float bottomU2 = 22.0f / 64.0f; // End at pixel 22 final float rightV1 = RIGHT_EDGE_RECT.v1();
float bottomV1 = 0.0f / 32.0f; // Start at pixel 0 final float rightV2 = RIGHT_EDGE_RECT.v2();
float bottomV2 = 1.0f / 32.0f; // End at pixel 1 final float rightPartV = (rightV2 - rightV1) / PARTS;
final float topU1 = TOP_RECT.u1();
final float topU2 = TOP_RECT.u2();
final float topV1 = TOP_RECT.v1();
final float topV2 = TOP_RECT.v2();
final float bottomU1 = BOTTOM_RECT.u1();
final float bottomU2 = BOTTOM_RECT.u2();
final float bottomV1 = BOTTOM_RECT.v1();
final float bottomV2 = BOTTOM_RECT.v2();
for (int i = 0; i < PARTS; i++) { for (int i = 0; i < PARTS; i++) {
float y3 = -(capePartHeight * i); float y3 = -(capePartHeight * i);
float y4 = -(capePartHeight * (i + 1)); float y4 = -(capePartHeight * (i + 1));
float totalVHeight = frontV2 - frontV1;
float partVHeight = totalVHeight / PARTS;
float curveOffsetTop = (float) Math.pow((double) (PARTS - i) / PARTS, 2) * curveMagnitude; float curveOffsetTop = getCurve(i, curveMagnitude, playerState);
float curveOffsetBottom = (float) Math.pow((double) (PARTS - i - 1) / PARTS, 2) float curveOffsetBottom = getCurve(i + 1, curveMagnitude, playerState);
* curveMagnitude;
// FRONT FACE // FRONT FACE (outside)
this.renderCapeQuad(vertexConsumer, matrixStack, this.renderCapeQuad(
new Vec3d(x2, y4, z2 + curveOffsetBottom), new Vec3d(x1, y4, z2 + vertexConsumer, matrixStack,
curveOffsetBottom), new Vec3d(x2, y4, z2 + curveOffsetBottom),
new Vec3d(x1, y3, z2 + curveOffsetTop), new Vec3d(x2, y3, z2 + new Vec3d(x1, y4, z2 + curveOffsetBottom),
curveOffsetTop), new Vec3d(x1, y3, z2 + curveOffsetTop), new Vec3d(x2, y3, z2 + curveOffsetTop),
frontU1, frontV2 - (partVHeight * i), frontU2, frontV2 - (partVHeight * (i + frontU1, frontV2 - (frontPartV * i),
1)), frontU2, frontV2 - (frontPartV * (i + 1)),
light, overlay, light, overlay,
0.0f, 0.0f, 1.0f, false); 0.0f, 0.0f, 1.0f, false);
// BACK FACE // BACK FACE (inside)
this.renderCapeQuad(vertexConsumer, matrixStack, this.renderCapeQuad(
vertexConsumer, matrixStack,
new Vec3d(x1, y4, z1 + curveOffsetBottom), new Vec3d(x1, y4, z1 + curveOffsetBottom),
new Vec3d(x2, y4, z1 + curveOffsetBottom), new Vec3d(x2, y4, z1 + curveOffsetBottom),
new Vec3d(x2, y3, z1 + curveOffsetTop), new Vec3d(x1, y3, z1 + curveOffsetTop), new Vec3d(x2, y3, z1 + curveOffsetTop), new Vec3d(x1, y3, z1 + curveOffsetTop),
backU1, backV2 - (partVHeight * i), backU2, backV2 - (partVHeight * (i + 1)), backU1, backV2 - (backPartV * i),
backU2, backV2 - (backPartV * (i + 1)),
light, overlay, light, overlay,
0.0f, 0.0f, 1.0f, false); 0.0f, 0.0f, 1.0f, false);
// LEFT FACE // LEFT FACE (thickness at x2)
this.renderCapeQuad(vertexConsumer, matrixStack, this.renderCapeQuad(
vertexConsumer, matrixStack,
new Vec3d(x2, y4, z1 + curveOffsetBottom), new Vec3d(x2, y4, z1 + curveOffsetBottom),
new Vec3d(x2, y4, z2 + curveOffsetBottom), new Vec3d(x2, y4, z2 + curveOffsetBottom),
new Vec3d(x2, y3, z2 + curveOffsetTop), new Vec3d(x2, y3, z1 + curveOffsetTop), new Vec3d(x2, y3, z2 + curveOffsetTop), new Vec3d(x2, y3, z1 + curveOffsetTop),
0.0f, frontV2 - (partVHeight * i), 1.0f / 64.0f, leftU1, leftV2 - (leftPartV * i),
frontV2 - (partVHeight * (i + 1)), leftU2, leftV2 - (leftPartV * (i + 1)),
light, overlay, light, overlay,
1.0f, 0.0f, 0.0f, false); 1.0f, 0.0f, 0.0f, false);
// RIGHT FACE // RIGHT FACE (thickness at x1)
this.renderCapeQuad(vertexConsumer, matrixStack, this.renderCapeQuad(
vertexConsumer, matrixStack,
new Vec3d(x1, y4, z2 + curveOffsetBottom), new Vec3d(x1, y4, z2 + curveOffsetBottom),
new Vec3d(x1, y4, z1 + curveOffsetBottom), new Vec3d(x1, y4, z1 + curveOffsetBottom),
new Vec3d(x1, y3, z1 + curveOffsetTop), new Vec3d(x1, y3, z2 + curveOffsetTop), new Vec3d(x1, y3, z1 + curveOffsetTop), new Vec3d(x1, y3, z2 + curveOffsetTop),
frontU2, frontV2 - (partVHeight * i), frontU2 + 1.0f / 64.0f, rightU1, rightV2 - (rightPartV * i),
frontV2 - (partVHeight * (i + 1)), rightU2, rightV2 - (rightPartV * (i + 1)),
light, overlay, light, overlay,
-1.0f, 0.0f, 0.0f, false); -1.0f, 0.0f, 0.0f, false);
} }
// TOP FACE // TOP FACE (shoulders edge) – use its dedicated strip
matrixStack.push(); matrixStack.push();
matrixStack.translate(0.0f, y2 + capeDepth, 0.0f); matrixStack.translate(0.0f, y2 + capeDepth, 0.0f);
matrixStack.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_X.rotationDegrees(90.0f)); matrixStack.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_X.rotationDegrees(90.0f));
matrixStack.translate(0.0f, -y2, 0.0f); matrixStack.translate(0.0f, -y2, 0.0f);
this.renderCapeQuad(vertexConsumer, matrixStack, this.renderCapeQuad(
vertexConsumer, matrixStack,
new Vec3d(x2, y2 + capeDepth, z2), new Vec3d(x1, y2 + capeDepth, z2), new Vec3d(x2, y2 + capeDepth, z2), new Vec3d(x1, y2 + capeDepth, z2),
new Vec3d(x1, y2, z2), new Vec3d(x1, y2, z2), new Vec3d(x2, y2, z2),
new Vec3d(x2, y2, z2),
topU1, topV1, topU2, topV2, topU1, topV1, topU2, topV2,
light, overlay, light, overlay,
0.0f, 1.0f, 0.0f, true); 0.0f, 1.0f, 0.0f, true);
matrixStack.pop(); matrixStack.pop();
// BOTTOM FACE // BOTTOM FACE – use bottom strip
float curveOffsetTop = (float) Math.pow(1.0f, 2) * curveMagnitude; float curveOffset = getCurve(0, curveMagnitude, playerState);
float curveOffsetBottom = (float) Math.pow(1.0f, 2) * curveMagnitude; this.renderCapeQuad(
vertexConsumer, matrixStack,
this.renderCapeQuad(vertexConsumer, matrixStack, new Vec3d(x2, 0.0f, z2 + curveOffset), new Vec3d(x1, 0.0f, z2 + curveOffset),
new Vec3d(x2, 0.0f, z2 + curveOffsetBottom), new Vec3d(x1, 0.0f, z1 + curveOffset), new Vec3d(x2, 0.0f, z1 + curveOffset),
new Vec3d(x1, 0.0f, z2 + curveOffsetBottom),
new Vec3d(x1, 0.0f, z1 + curveOffsetTop), new Vec3d(x2, 0.0f, z1 + curveOffsetTop),
bottomU1, bottomV1, bottomU2, bottomV2, bottomU1, bottomV1, bottomU2, bottomV2,
light, overlay, light, overlay,
0.0f, 0.0f, 1.0f, false); 0.0f, 0.0f, 1.0f, false);
@@ -282,9 +297,7 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
} }
Identifier customCape = Cloaks.getCurrentCloakTexture(uuid); Identifier customCape = Cloaks.getCurrentCloakTexture(uuid);
if (customCape == null if (customCape == null || this.hasCustomModelForLayer(playerEntityRenderState.equippedChestStack,
|| this.hasCustomModelForLayer(
playerEntityRenderState.equippedChestStack,
LayerType.WINGS)) { LayerType.WINGS)) {
return; return;
} }
@@ -297,44 +310,44 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
light = (skyLight << 20) | (blockLight << 4); light = (skyLight << 20) | (blockLight << 4);
matrixStack.push(); matrixStack.push();
VertexConsumer vertexConsumer = vertexConsumerProvider VertexConsumer vertexConsumer = vertexConsumerProvider
.getBuffer(RenderLayer.getEntityAlpha(customCape)); .getBuffer(RenderLayer.getEntityAlpha(customCape));
if (SaturnClientConfig.bendyCloaks.value) { float targetVelocity = ((6.0F + playerEntityRenderState.field_53537 / 2.0F
float targetVelocity = ((6.0F
+ playerEntityRenderState.field_53537 / 2.0F
+ playerEntityRenderState.field_53536) * 0.02f); + playerEntityRenderState.field_53536) * 0.02f);
targetVelocity = Math.max(0.0f, targetVelocity - 0.1f); targetVelocity = Math.max(0.0f, targetVelocity - 0.1f);
float accelerationRate = 0.02f; float accelerationRate = 0.02f;
this.currentVelocity = this.currentVelocity this.currentVelocity = this.currentVelocity
+ (targetVelocity - this.currentVelocity) + (targetVelocity - this.currentVelocity) * accelerationRate;
* accelerationRate;
float rotation = this.currentVelocity * 72.0f; float rotation = this.currentVelocity * 72.0f;
float curve = this.currentVelocity * 0.4f; float curve = this.currentVelocity * 0.4f;
matrixStack.translate(0.0f, -0.25f, 0.0f); if (playerEntityRenderState.sneaking && playerEntityRenderState.isInSneakingPose) {
if (this.hasCustomModelForLayer( matrixStack.translate(0, 0.24f, 0);
playerEntityRenderState.equippedChestStack, matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(27.0f));
LayerType.HUMANOID)) { curve += 0.2f;
matrixStack.translate(0.0F, -0.053125F, 0.06875F);
} }
renderCape(matrixStack, vertexConsumer, playerEntityRenderState, light, matrixStack.translate(0.0f, -0.25f, 0.0f);
OverlayTexture.DEFAULT_UV,
Math.min(rotation, 60.0f), Math.min(curve, 0.5f));
} else {
if (this.hasCustomModelForLayer(playerEntityRenderState.equippedChestStack, if (this.hasCustomModelForLayer(playerEntityRenderState.equippedChestStack,
LayerType.HUMANOID)) { LayerType.HUMANOID)) {
matrixStack.translate(0.0F, -0.053125F, 0.06875F); matrixStack.translate(0.0F, -0.053125F, 0.06875F);
} }
((PlayerEntityModel) this.getContextModel()).copyTransforms(this.model);
this.model.setAngles(playerEntityRenderState); if (playerEntityRenderState.isSwimming) {
this.model.render(matrixStack, vertexConsumer, light, OverlayTexture.DEFAULT_UV); curve = 0.0f;
rotation = 0.0f;
} }
if (!SaturnClientConfig.bendyCloaks.value) {
curve = 0.0f;
}
renderCape(matrixStack, vertexConsumer, playerEntityRenderState, light,
OverlayTexture.DEFAULT_UV, Math.min(rotation, 60.0f), Math.min(curve, 0.5f));
matrixStack.pop(); matrixStack.pop();
} }
} }
@@ -25,6 +25,6 @@ public abstract class PlayerEntityRendererMixin
@Inject(method = "<init>", at = @At("TAIL")) @Inject(method = "<init>", at = @At("TAIL"))
private void addCustomFeatureRenderer(EntityRendererFactory.Context ctx, boolean slim, CallbackInfo ci) { private void addCustomFeatureRenderer(EntityRendererFactory.Context ctx, boolean slim, CallbackInfo ci) {
this.addFeature(new HatFeatureRenderer(this)); this.addFeature(new HatFeatureRenderer(this));
this.addFeature(new CloakFeatureRenderer(this, ctx.getEntityModels(), ctx.getEquipmentModelLoader())); this.addFeature(new CloakFeatureRenderer(this, ctx.getEquipmentModelLoader()));
} }
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 18 KiB