minecraft-src/net/minecraft/client/renderer/BlockEntityWithoutLevelRenderer.java
2025-07-04 01:41:11 +03:00

173 lines
8.6 KiB
Java

package net.minecraft.client.renderer;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Objects;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ShieldModel;
import net.minecraft.client.model.SkullModelBase;
import net.minecraft.client.model.TridentModel;
import net.minecraft.client.model.geom.EntityModelSet;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.renderer.blockentity.BannerRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import net.minecraft.client.renderer.blockentity.SkullBlockRenderer;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ResolvableProfile;
import net.minecraft.world.level.block.AbstractBannerBlock;
import net.minecraft.world.level.block.AbstractSkullBlock;
import net.minecraft.world.level.block.BedBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.ShulkerBoxBlock;
import net.minecraft.world.level.block.SkullBlock;
import net.minecraft.world.level.block.entity.BannerBlockEntity;
import net.minecraft.world.level.block.entity.BannerPatternLayers;
import net.minecraft.world.level.block.entity.BedBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
import net.minecraft.world.level.block.entity.ConduitBlockEntity;
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
import net.minecraft.world.level.block.entity.EnderChestBlockEntity;
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
import net.minecraft.world.level.block.entity.TrappedChestBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
@Environment(EnvType.CLIENT)
public class BlockEntityWithoutLevelRenderer implements ResourceManagerReloadListener {
private static final ShulkerBoxBlockEntity[] SHULKER_BOXES = (ShulkerBoxBlockEntity[])Arrays.stream(DyeColor.values())
.sorted(Comparator.comparingInt(DyeColor::getId))
.map(dyeColor -> new ShulkerBoxBlockEntity(dyeColor, BlockPos.ZERO, Blocks.SHULKER_BOX.defaultBlockState()))
.toArray(ShulkerBoxBlockEntity[]::new);
private static final ShulkerBoxBlockEntity DEFAULT_SHULKER_BOX = new ShulkerBoxBlockEntity(BlockPos.ZERO, Blocks.SHULKER_BOX.defaultBlockState());
private final ChestBlockEntity chest = new ChestBlockEntity(BlockPos.ZERO, Blocks.CHEST.defaultBlockState());
private final ChestBlockEntity trappedChest = new TrappedChestBlockEntity(BlockPos.ZERO, Blocks.TRAPPED_CHEST.defaultBlockState());
private final EnderChestBlockEntity enderChest = new EnderChestBlockEntity(BlockPos.ZERO, Blocks.ENDER_CHEST.defaultBlockState());
private final BannerBlockEntity banner = new BannerBlockEntity(BlockPos.ZERO, Blocks.WHITE_BANNER.defaultBlockState());
private final BedBlockEntity bed = new BedBlockEntity(BlockPos.ZERO, Blocks.RED_BED.defaultBlockState());
private final ConduitBlockEntity conduit = new ConduitBlockEntity(BlockPos.ZERO, Blocks.CONDUIT.defaultBlockState());
private final DecoratedPotBlockEntity decoratedPot = new DecoratedPotBlockEntity(BlockPos.ZERO, Blocks.DECORATED_POT.defaultBlockState());
private ShieldModel shieldModel;
private TridentModel tridentModel;
private Map<SkullBlock.Type, SkullModelBase> skullModels;
private final BlockEntityRenderDispatcher blockEntityRenderDispatcher;
private final EntityModelSet entityModelSet;
public BlockEntityWithoutLevelRenderer(BlockEntityRenderDispatcher blockEntityRenderDispatcher, EntityModelSet entityModelSet) {
this.blockEntityRenderDispatcher = blockEntityRenderDispatcher;
this.entityModelSet = entityModelSet;
}
@Override
public void onResourceManagerReload(ResourceManager resourceManager) {
this.shieldModel = new ShieldModel(this.entityModelSet.bakeLayer(ModelLayers.SHIELD));
this.tridentModel = new TridentModel(this.entityModelSet.bakeLayer(ModelLayers.TRIDENT));
this.skullModels = SkullBlockRenderer.createSkullRenderers(this.entityModelSet);
}
public void renderByItem(ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {
Item item = stack.getItem();
if (item instanceof BlockItem) {
Block block = ((BlockItem)item).getBlock();
if (block instanceof AbstractSkullBlock abstractSkullBlock) {
ResolvableProfile resolvableProfile = stack.get(DataComponents.PROFILE);
if (resolvableProfile != null && !resolvableProfile.isResolved()) {
stack.remove(DataComponents.PROFILE);
resolvableProfile.resolve().thenAcceptAsync(resolvableProfilex -> stack.set(DataComponents.PROFILE, resolvableProfilex), Minecraft.getInstance());
resolvableProfile = null;
}
SkullModelBase skullModelBase = (SkullModelBase)this.skullModels.get(abstractSkullBlock.getType());
RenderType renderType = SkullBlockRenderer.getRenderType(abstractSkullBlock.getType(), resolvableProfile);
SkullBlockRenderer.renderSkull(null, 180.0F, 0.0F, poseStack, buffer, packedLight, skullModelBase, renderType);
} else {
BlockState blockState = block.defaultBlockState();
BlockEntity blockEntity;
if (block instanceof AbstractBannerBlock) {
this.banner.fromItem(stack, ((AbstractBannerBlock)block).getColor());
blockEntity = this.banner;
} else if (block instanceof BedBlock) {
this.bed.setColor(((BedBlock)block).getColor());
blockEntity = this.bed;
} else if (blockState.is(Blocks.CONDUIT)) {
blockEntity = this.conduit;
} else if (blockState.is(Blocks.CHEST)) {
blockEntity = this.chest;
} else if (blockState.is(Blocks.ENDER_CHEST)) {
blockEntity = this.enderChest;
} else if (blockState.is(Blocks.TRAPPED_CHEST)) {
blockEntity = this.trappedChest;
} else if (blockState.is(Blocks.DECORATED_POT)) {
this.decoratedPot.setFromItem(stack);
blockEntity = this.decoratedPot;
} else {
if (!(block instanceof ShulkerBoxBlock)) {
return;
}
DyeColor dyeColor = ShulkerBoxBlock.getColorFromItem(item);
if (dyeColor == null) {
blockEntity = DEFAULT_SHULKER_BOX;
} else {
blockEntity = SHULKER_BOXES[dyeColor.getId()];
}
}
this.blockEntityRenderDispatcher.renderItem(blockEntity, poseStack, buffer, packedLight, packedOverlay);
}
} else {
if (stack.is(Items.SHIELD)) {
BannerPatternLayers bannerPatternLayers = stack.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY);
DyeColor dyeColor2 = stack.get(DataComponents.BASE_COLOR);
boolean bl = !bannerPatternLayers.layers().isEmpty() || dyeColor2 != null;
poseStack.pushPose();
poseStack.scale(1.0F, -1.0F, -1.0F);
Material material = bl ? ModelBakery.SHIELD_BASE : ModelBakery.NO_PATTERN_SHIELD;
VertexConsumer vertexConsumer = material.sprite()
.wrap(ItemRenderer.getFoilBufferDirect(buffer, this.shieldModel.renderType(material.atlasLocation()), true, stack.hasFoil()));
this.shieldModel.handle().render(poseStack, vertexConsumer, packedLight, packedOverlay);
if (bl) {
BannerRenderer.renderPatterns(
poseStack,
buffer,
packedLight,
packedOverlay,
this.shieldModel.plate(),
material,
false,
(DyeColor)Objects.requireNonNullElse(dyeColor2, DyeColor.WHITE),
bannerPatternLayers,
stack.hasFoil()
);
} else {
this.shieldModel.plate().render(poseStack, vertexConsumer, packedLight, packedOverlay);
}
poseStack.popPose();
} else if (stack.is(Items.TRIDENT)) {
poseStack.pushPose();
poseStack.scale(1.0F, -1.0F, -1.0F);
VertexConsumer vertexConsumer2 = ItemRenderer.getFoilBufferDirect(buffer, this.tridentModel.renderType(TridentModel.TEXTURE), false, stack.hasFoil());
this.tridentModel.renderToBuffer(poseStack, vertexConsumer2, packedLight, packedOverlay);
poseStack.popPose();
}
}
}
}