package net.minecraft.client.renderer.entity.layers; import com.mojang.blaze3d.vertex.PoseStack; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import java.io.IOException; import java.util.Optional; import java.util.function.UnaryOperator; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.Util; import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.VillagerLikeModel; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.RenderLayerParent; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; import net.minecraft.client.renderer.entity.state.VillagerDataHolderRenderState; import net.minecraft.client.resources.metadata.animation.VillagerMetadataSection; import net.minecraft.core.DefaultedRegistry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.Mth; import net.minecraft.world.entity.npc.VillagerData; import net.minecraft.world.entity.npc.VillagerProfession; import net.minecraft.world.entity.npc.VillagerType; @Environment(EnvType.CLIENT) public class VillagerProfessionLayer & VillagerLikeModel> extends RenderLayer { private static final Int2ObjectMap LEVEL_LOCATIONS = Util.make(new Int2ObjectOpenHashMap<>(), int2ObjectOpenHashMap -> { int2ObjectOpenHashMap.put(1, ResourceLocation.withDefaultNamespace("stone")); int2ObjectOpenHashMap.put(2, ResourceLocation.withDefaultNamespace("iron")); int2ObjectOpenHashMap.put(3, ResourceLocation.withDefaultNamespace("gold")); int2ObjectOpenHashMap.put(4, ResourceLocation.withDefaultNamespace("emerald")); int2ObjectOpenHashMap.put(5, ResourceLocation.withDefaultNamespace("diamond")); }); private final Object2ObjectMap typeHatCache = new Object2ObjectOpenHashMap<>(); private final Object2ObjectMap professionHatCache = new Object2ObjectOpenHashMap<>(); private final ResourceManager resourceManager; private final String path; public VillagerProfessionLayer(RenderLayerParent renderer, ResourceManager resourceManager, String path) { super(renderer); this.resourceManager = resourceManager; this.path = path; } public void render(PoseStack poseStack, MultiBufferSource multiBufferSource, int i, S livingEntityRenderState, float f, float g) { if (!livingEntityRenderState.isInvisible) { VillagerData villagerData = livingEntityRenderState.getVillagerData(); VillagerType villagerType = villagerData.getType(); VillagerProfession villagerProfession = villagerData.getProfession(); VillagerMetadataSection.Hat hat = this.getHatData(this.typeHatCache, "type", BuiltInRegistries.VILLAGER_TYPE, villagerType); VillagerMetadataSection.Hat hat2 = this.getHatData(this.professionHatCache, "profession", BuiltInRegistries.VILLAGER_PROFESSION, villagerProfession); M entityModel = this.getParentModel(); entityModel.hatVisible(hat2 == VillagerMetadataSection.Hat.NONE || hat2 == VillagerMetadataSection.Hat.PARTIAL && hat != VillagerMetadataSection.Hat.FULL); ResourceLocation resourceLocation = this.getResourceLocation("type", BuiltInRegistries.VILLAGER_TYPE.getKey(villagerType)); renderColoredCutoutModel(entityModel, resourceLocation, poseStack, multiBufferSource, i, livingEntityRenderState, -1); entityModel.hatVisible(true); if (villagerProfession != VillagerProfession.NONE && !livingEntityRenderState.isBaby) { ResourceLocation resourceLocation2 = this.getResourceLocation("profession", BuiltInRegistries.VILLAGER_PROFESSION.getKey(villagerProfession)); renderColoredCutoutModel(entityModel, resourceLocation2, poseStack, multiBufferSource, i, livingEntityRenderState, -1); if (villagerProfession != VillagerProfession.NITWIT) { ResourceLocation resourceLocation3 = this.getResourceLocation( "profession_level", LEVEL_LOCATIONS.get(Mth.clamp(villagerData.getLevel(), 1, LEVEL_LOCATIONS.size())) ); renderColoredCutoutModel(entityModel, resourceLocation3, poseStack, multiBufferSource, i, livingEntityRenderState, -1); } } } } private ResourceLocation getResourceLocation(String folder, ResourceLocation location) { return location.withPath((UnaryOperator)(string2 -> "textures/entity/" + this.path + "/" + folder + "/" + string2 + ".png")); } public VillagerMetadataSection.Hat getHatData(Object2ObjectMap cache, String folder, DefaultedRegistry registry, K key) { return cache.computeIfAbsent( key, object2 -> (VillagerMetadataSection.Hat)this.resourceManager.getResource(this.getResourceLocation(folder, registry.getKey(key))).flatMap(resource -> { try { return resource.metadata().getSection(VillagerMetadataSection.TYPE).map(VillagerMetadataSection::hat); } catch (IOException var2) { return Optional.empty(); } }).orElse(VillagerMetadataSection.Hat.NONE) ); } }