minecraft-src/net/minecraft/client/renderer/special/SkullSpecialRenderer.java
2025-09-18 12:27:44 +00:00

86 lines
3.3 KiB
Java

package net.minecraft.client.renderer.special;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.Optional;
import java.util.Set;
import java.util.function.UnaryOperator;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.model.SkullModelBase;
import net.minecraft.client.model.geom.EntityModelSet;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.SkullBlockRenderer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.level.block.SkullBlock;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
@Environment(EnvType.CLIENT)
public class SkullSpecialRenderer implements NoDataSpecialModelRenderer {
private final SkullModelBase model;
private final float animation;
private final RenderType renderType;
public SkullSpecialRenderer(SkullModelBase model, float animation, RenderType renderType) {
this.model = model;
this.animation = animation;
this.renderType = renderType;
}
@Override
public void render(
ItemDisplayContext displayContext, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay, boolean hasFoilType
) {
SkullBlockRenderer.renderSkull(null, 180.0F, this.animation, poseStack, bufferSource, packedLight, this.model, this.renderType);
}
@Override
public void getExtents(Set<Vector3f> output) {
PoseStack poseStack = new PoseStack();
poseStack.translate(0.5F, 0.0F, 0.5F);
poseStack.scale(-1.0F, -1.0F, 1.0F);
this.model.setupAnim(this.animation, 180.0F, 0.0F);
this.model.root().getExtentsForGui(poseStack, output);
}
@Environment(EnvType.CLIENT)
public record Unbaked(SkullBlock.Type kind, Optional<ResourceLocation> textureOverride, float animation) implements SpecialModelRenderer.Unbaked {
public static final MapCodec<SkullSpecialRenderer.Unbaked> MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
SkullBlock.Type.CODEC.fieldOf("kind").forGetter(SkullSpecialRenderer.Unbaked::kind),
ResourceLocation.CODEC.optionalFieldOf("texture").forGetter(SkullSpecialRenderer.Unbaked::textureOverride),
Codec.FLOAT.optionalFieldOf("animation", 0.0F).forGetter(SkullSpecialRenderer.Unbaked::animation)
)
.apply(instance, SkullSpecialRenderer.Unbaked::new)
);
public Unbaked(SkullBlock.Type type) {
this(type, Optional.empty(), 0.0F);
}
@Override
public MapCodec<SkullSpecialRenderer.Unbaked> type() {
return MAP_CODEC;
}
@Nullable
@Override
public SpecialModelRenderer<?> bake(EntityModelSet modelSet) {
SkullModelBase skullModelBase = SkullBlockRenderer.createModel(modelSet, this.kind);
ResourceLocation resourceLocation = (ResourceLocation)this.textureOverride
.map(resourceLocationx -> resourceLocationx.withPath((UnaryOperator<String>)(string -> "textures/entity/" + string + ".png")))
.orElse(null);
if (skullModelBase == null) {
return null;
} else {
RenderType renderType = SkullBlockRenderer.getSkullRenderType(this.kind, resourceLocation);
return new SkullSpecialRenderer(skullModelBase, this.animation, renderType);
}
}
}
}