better cloak rendering

This commit is contained in:
2025-04-11 23:40:40 +02:00
parent 719e5245d5
commit c68b68db57
7 changed files with 94 additions and 45 deletions
@@ -0,0 +1,90 @@
package org.saturnclient.saturnclient.cosmetics;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.auth.SaturnPlayer;
import org.saturnclient.saturnclient.auth.SaturnSocket;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.equipment.EquipmentModel;
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;
import net.minecraft.item.ItemStack;
import net.minecraft.item.equipment.EquipmentAsset;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.Identifier;
public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderState, PlayerEntityModel> {
private final BipedEntityModel<PlayerEntityRenderState> model;
private final EquipmentModelLoader equipmentModelLoader;
public CloakFeatureRenderer(FeatureRendererContext<PlayerEntityRenderState, PlayerEntityModel> context,
LoadedEntityModels modelLoader, EquipmentModelLoader equipmentModelLoader) {
super(context);
this.model = new PlayerCapeModel<PlayerEntityRenderState>(
modelLoader.getModelPart(EntityModelLayers.PLAYER_CAPE));
this.equipmentModelLoader = equipmentModelLoader;
}
private boolean hasCustomModelForLayer(ItemStack stack, EquipmentModel.LayerType layerType) {
EquippableComponent equippableComponent = (EquippableComponent) stack.get(DataComponentTypes.EQUIPPABLE);
if (equippableComponent != null && !equippableComponent.assetId().isEmpty()) {
EquipmentModel equipmentModel = this.equipmentModelLoader
.get((RegistryKey<EquipmentAsset>) equippableComponent.assetId().get());
return !equipmentModel.getLayers(layerType).isEmpty();
} else {
return false;
}
}
public void render(MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i,
PlayerEntityRenderState playerEntityRenderState, float f, float g) {
if (!playerEntityRenderState.invisible && playerEntityRenderState.capeVisible) {
SkinTextures skinTextures = playerEntityRenderState.skinTextures;
if (skinTextures.capeTexture() == null) {
String name = playerEntityRenderState.name;
String uuid = SaturnSocket.playerNames.get(name);
if (uuid == null || !SaturnSocket.players.containsKey(uuid)) {
return;
}
SaturnPlayer player = SaturnSocket.players.get(uuid);
if (player.cloak == "") {
return;
}
Identifier customCape = Identifier.of(SaturnClient.MOD_ID, "textures/cloaks/" + player.cloak + ".png");
if (!this.hasCustomModelForLayer(playerEntityRenderState.equippedChestStack, LayerType.WINGS)) {
matrixStack.push();
if (this.hasCustomModelForLayer(playerEntityRenderState.equippedChestStack, LayerType.HUMANOID)) {
matrixStack.translate(0.0F, -0.053125F, 0.06875F);
}
VertexConsumer vertexConsumer = vertexConsumerProvider
.getBuffer(RenderLayer.getEntityAlpha(customCape));
((PlayerEntityModel) this.getContextModel()).copyTransforms(this.model);
this.model.setAngles(playerEntityRenderState);
this.model.render(matrixStack, vertexConsumer, 0xF000F0, OverlayTexture.DEFAULT_UV);
matrixStack.pop();
}
}
}
}
}
@@ -20,7 +20,7 @@ import org.saturnclient.saturnclient.SaturnClient;
* Originally created by IIpho3nix and modified for Saturn Client by leo. * Originally created by IIpho3nix and modified for Saturn Client by leo.
*/ */
public class Cloaks { public class Cloaks {
private static final String[] ANIMATED_CLOAKS = { "glitch" }; private static final String[] ANIMATED_CLOAKS = { };
private static final String CLOAKS_RESOURCE_PATH = "assets/saturnclient/textures/cloaks/"; private static final String CLOAKS_RESOURCE_PATH = "assets/saturnclient/textures/cloaks/";
public static final List<String> availableCloaks = new ArrayList<>(); public static final List<String> availableCloaks = new ArrayList<>();
@@ -1,42 +0,0 @@
package org.saturnclient.saturnclient.mixin;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.util.SkinTextures;
import net.minecraft.util.Identifier;
import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/**
* Mixin for handling custom cloaks in the AbstractClientPlayerEntity class.
* Injects custom cloak textures for players who have them assigned.
*/
@Mixin(AbstractClientPlayerEntity.class)
@Environment(EnvType.CLIENT)
public abstract class CapeRenderer {
/**
* Injects custom cloak textures into the player's skin textures.
*/
@Inject(method = "getSkinTextures", at = @At("RETURN"), cancellable = true)
private void injectCustomTextures(CallbackInfoReturnable<SkinTextures> cir) {
AbstractClientPlayerEntity player = (AbstractClientPlayerEntity) (Object) this;
String uuid = player.getUuidAsString().replace("-", "");
Identifier cloakTexture = Cloaks.getCurrentCloakTexture(uuid);
if (cloakTexture != null) {
SkinTextures textures = cir.getReturnValue();
cir.setReturnValue(new SkinTextures(
textures.texture(),
textures.textureUrl(),
cloakTexture,
textures.elytraTexture(),
textures.model(),
textures.secure()));
}
}
}
@@ -7,6 +7,7 @@ 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.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import org.saturnclient.saturnclient.cosmetics.CloakFeatureRenderer;
import org.saturnclient.saturnclient.cosmetics.HatFeatureRenderer; import org.saturnclient.saturnclient.cosmetics.HatFeatureRenderer;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -22,7 +23,8 @@ public abstract class PlayerEntityRendererMixin
} }
@Inject(method = "<init>", at = @At("TAIL")) @Inject(method = "<init>", at = @At("TAIL"))
private void addCustomFeatureRenderer(EntityRendererFactory.Context context, 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()));
} }
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

@@ -4,7 +4,6 @@
"package": "org.saturnclient.saturnclient.mixin", "package": "org.saturnclient.saturnclient.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"client": [ "client": [
"CapeRenderer",
"TabListMixin", "TabListMixin",
"NameTagMixin", "NameTagMixin",
"PlayerEntityRendererMixin", "PlayerEntityRendererMixin",