122 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.client.renderer.blockentity;
 | |
| 
 | |
| import com.google.common.collect.Maps;
 | |
| import com.mojang.blaze3d.vertex.PoseStack;
 | |
| import com.mojang.blaze3d.vertex.VertexConsumer;
 | |
| import java.util.Map;
 | |
| import java.util.function.Function;
 | |
| import net.fabricmc.api.EnvType;
 | |
| import net.fabricmc.api.Environment;
 | |
| import net.minecraft.Util;
 | |
| import net.minecraft.client.Minecraft;
 | |
| import net.minecraft.client.model.PiglinHeadModel;
 | |
| import net.minecraft.client.model.SkullModel;
 | |
| import net.minecraft.client.model.SkullModelBase;
 | |
| import net.minecraft.client.model.dragon.DragonHeadModel;
 | |
| import net.minecraft.client.model.geom.EntityModelSet;
 | |
| import net.minecraft.client.model.geom.ModelLayers;
 | |
| import net.minecraft.client.renderer.MultiBufferSource;
 | |
| import net.minecraft.client.renderer.RenderType;
 | |
| import net.minecraft.client.renderer.texture.OverlayTexture;
 | |
| import net.minecraft.client.resources.DefaultPlayerSkin;
 | |
| import net.minecraft.core.Direction;
 | |
| import net.minecraft.resources.ResourceLocation;
 | |
| import net.minecraft.world.item.component.ResolvableProfile;
 | |
| import net.minecraft.world.level.block.AbstractSkullBlock;
 | |
| import net.minecraft.world.level.block.SkullBlock;
 | |
| import net.minecraft.world.level.block.WallSkullBlock;
 | |
| import net.minecraft.world.level.block.entity.SkullBlockEntity;
 | |
| import net.minecraft.world.level.block.state.BlockState;
 | |
| import net.minecraft.world.level.block.state.properties.RotationSegment;
 | |
| import net.minecraft.world.phys.Vec3;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| @Environment(EnvType.CLIENT)
 | |
| public class SkullBlockRenderer implements BlockEntityRenderer<SkullBlockEntity> {
 | |
| 	private final Function<SkullBlock.Type, SkullModelBase> modelByType;
 | |
| 	private static final Map<SkullBlock.Type, ResourceLocation> SKIN_BY_TYPE = Util.make(Maps.<SkullBlock.Type, ResourceLocation>newHashMap(), hashMap -> {
 | |
| 		hashMap.put(SkullBlock.Types.SKELETON, ResourceLocation.withDefaultNamespace("textures/entity/skeleton/skeleton.png"));
 | |
| 		hashMap.put(SkullBlock.Types.WITHER_SKELETON, ResourceLocation.withDefaultNamespace("textures/entity/skeleton/wither_skeleton.png"));
 | |
| 		hashMap.put(SkullBlock.Types.ZOMBIE, ResourceLocation.withDefaultNamespace("textures/entity/zombie/zombie.png"));
 | |
| 		hashMap.put(SkullBlock.Types.CREEPER, ResourceLocation.withDefaultNamespace("textures/entity/creeper/creeper.png"));
 | |
| 		hashMap.put(SkullBlock.Types.DRAGON, ResourceLocation.withDefaultNamespace("textures/entity/enderdragon/dragon.png"));
 | |
| 		hashMap.put(SkullBlock.Types.PIGLIN, ResourceLocation.withDefaultNamespace("textures/entity/piglin/piglin.png"));
 | |
| 		hashMap.put(SkullBlock.Types.PLAYER, DefaultPlayerSkin.getDefaultTexture());
 | |
| 	});
 | |
| 
 | |
| 	@Nullable
 | |
| 	public static SkullModelBase createModel(EntityModelSet modelSet, SkullBlock.Type type) {
 | |
| 		if (type instanceof SkullBlock.Types types) {
 | |
| 			return (SkullModelBase)(switch (types) {
 | |
| 				case SKELETON -> new SkullModel(modelSet.bakeLayer(ModelLayers.SKELETON_SKULL));
 | |
| 				case WITHER_SKELETON -> new SkullModel(modelSet.bakeLayer(ModelLayers.WITHER_SKELETON_SKULL));
 | |
| 				case PLAYER -> new SkullModel(modelSet.bakeLayer(ModelLayers.PLAYER_HEAD));
 | |
| 				case ZOMBIE -> new SkullModel(modelSet.bakeLayer(ModelLayers.ZOMBIE_HEAD));
 | |
| 				case CREEPER -> new SkullModel(modelSet.bakeLayer(ModelLayers.CREEPER_HEAD));
 | |
| 				case DRAGON -> new DragonHeadModel(modelSet.bakeLayer(ModelLayers.DRAGON_SKULL));
 | |
| 				case PIGLIN -> new PiglinHeadModel(modelSet.bakeLayer(ModelLayers.PIGLIN_HEAD));
 | |
| 			});
 | |
| 		} else {
 | |
| 			return null;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public SkullBlockRenderer(BlockEntityRendererProvider.Context context) {
 | |
| 		EntityModelSet entityModelSet = context.getModelSet();
 | |
| 		this.modelByType = Util.memoize((Function<SkullBlock.Type, SkullModelBase>)(type -> createModel(entityModelSet, type)));
 | |
| 	}
 | |
| 
 | |
| 	public void render(
 | |
| 		SkullBlockEntity blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay, Vec3 cameraPos
 | |
| 	) {
 | |
| 		float f = blockEntity.getAnimation(partialTick);
 | |
| 		BlockState blockState = blockEntity.getBlockState();
 | |
| 		boolean bl = blockState.getBlock() instanceof WallSkullBlock;
 | |
| 		Direction direction = bl ? blockState.getValue(WallSkullBlock.FACING) : null;
 | |
| 		int i = bl ? RotationSegment.convertToSegment(direction.getOpposite()) : (Integer)blockState.getValue(SkullBlock.ROTATION);
 | |
| 		float g = RotationSegment.convertToDegrees(i);
 | |
| 		SkullBlock.Type type = ((AbstractSkullBlock)blockState.getBlock()).getType();
 | |
| 		SkullModelBase skullModelBase = (SkullModelBase)this.modelByType.apply(type);
 | |
| 		RenderType renderType = getRenderType(type, blockEntity.getOwnerProfile());
 | |
| 		renderSkull(direction, g, f, poseStack, bufferSource, packedLight, skullModelBase, renderType);
 | |
| 	}
 | |
| 
 | |
| 	public static void renderSkull(
 | |
| 		@Nullable Direction direction,
 | |
| 		float yRot,
 | |
| 		float mouthAnimation,
 | |
| 		PoseStack poseStack,
 | |
| 		MultiBufferSource bufferSource,
 | |
| 		int packedLight,
 | |
| 		SkullModelBase model,
 | |
| 		RenderType renderType
 | |
| 	) {
 | |
| 		poseStack.pushPose();
 | |
| 		if (direction == null) {
 | |
| 			poseStack.translate(0.5F, 0.0F, 0.5F);
 | |
| 		} else {
 | |
| 			float f = 0.25F;
 | |
| 			poseStack.translate(0.5F - direction.getStepX() * 0.25F, 0.25F, 0.5F - direction.getStepZ() * 0.25F);
 | |
| 		}
 | |
| 
 | |
| 		poseStack.scale(-1.0F, -1.0F, 1.0F);
 | |
| 		VertexConsumer vertexConsumer = bufferSource.getBuffer(renderType);
 | |
| 		model.setupAnim(mouthAnimation, yRot, 0.0F);
 | |
| 		model.renderToBuffer(poseStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY);
 | |
| 		poseStack.popPose();
 | |
| 	}
 | |
| 
 | |
| 	public static RenderType getRenderType(SkullBlock.Type type, @Nullable ResolvableProfile profile) {
 | |
| 		return type == SkullBlock.Types.PLAYER && profile != null
 | |
| 			? getPlayerSkinRenderType(Minecraft.getInstance().getSkinManager().getInsecureSkin(profile.gameProfile()).texture())
 | |
| 			: getSkullRenderType(type, null);
 | |
| 	}
 | |
| 
 | |
| 	public static RenderType getSkullRenderType(SkullBlock.Type type, @Nullable ResourceLocation textureLocation) {
 | |
| 		return RenderType.entityCutoutNoCullZOffset(textureLocation != null ? textureLocation : (ResourceLocation)SKIN_BY_TYPE.get(type));
 | |
| 	}
 | |
| 
 | |
| 	public static RenderType getPlayerSkinRenderType(ResourceLocation textureLocation) {
 | |
| 		return RenderType.entityTranslucent(textureLocation);
 | |
| 	}
 | |
| }
 |