minecraft-src/net/minecraft/client/renderer/entity/AbstractMinecartRenderer.java
2025-07-04 03:45:38 +03:00

180 lines
7.9 KiB
Java

package net.minecraft.client.renderer.entity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Axis;
import java.util.Objects;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.model.MinecartModel;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.entity.EntityRendererProvider.Context;
import net.minecraft.client.renderer.entity.state.MinecartRenderState;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.entity.vehicle.NewMinecartBehavior;
import net.minecraft.world.entity.vehicle.OldMinecartBehavior;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
@Environment(EnvType.CLIENT)
public abstract class AbstractMinecartRenderer<T extends AbstractMinecart, S extends MinecartRenderState> extends EntityRenderer<T, S> {
private static final ResourceLocation MINECART_LOCATION = ResourceLocation.withDefaultNamespace("textures/entity/minecart.png");
private static final float DISPLAY_BLOCK_SCALE = 0.75F;
protected final MinecartModel model;
private final BlockRenderDispatcher blockRenderer;
public AbstractMinecartRenderer(Context context, ModelLayerLocation modelLayer) {
super(context);
this.shadowRadius = 0.7F;
this.model = new MinecartModel(context.bakeLayer(modelLayer));
this.blockRenderer = context.getBlockRenderDispatcher();
}
public void render(S minecartRenderState, PoseStack poseStack, MultiBufferSource multiBufferSource, int i) {
super.render(minecartRenderState, poseStack, multiBufferSource, i);
poseStack.pushPose();
long l = minecartRenderState.offsetSeed;
float f = (((float)(l >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float g = (((float)(l >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float h = (((float)(l >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
poseStack.translate(f, g, h);
if (minecartRenderState.isNewRender) {
newRender(minecartRenderState, poseStack);
} else {
oldRender(minecartRenderState, poseStack);
}
float j = minecartRenderState.hurtTime;
if (j > 0.0F) {
poseStack.mulPose(Axis.XP.rotationDegrees(Mth.sin(j) * j * minecartRenderState.damageTime / 10.0F * minecartRenderState.hurtDir));
}
BlockState blockState = minecartRenderState.displayBlockState;
if (blockState.getRenderShape() != RenderShape.INVISIBLE) {
poseStack.pushPose();
poseStack.scale(0.75F, 0.75F, 0.75F);
poseStack.translate(-0.5F, (minecartRenderState.displayOffset - 8) / 16.0F, 0.5F);
poseStack.mulPose(Axis.YP.rotationDegrees(90.0F));
this.renderMinecartContents(minecartRenderState, blockState, poseStack, multiBufferSource, i);
poseStack.popPose();
}
poseStack.scale(-1.0F, -1.0F, 1.0F);
this.model.setupAnim(minecartRenderState);
VertexConsumer vertexConsumer = multiBufferSource.getBuffer(this.model.renderType(MINECART_LOCATION));
this.model.renderToBuffer(poseStack, vertexConsumer, i, OverlayTexture.NO_OVERLAY);
poseStack.popPose();
}
private static <S extends MinecartRenderState> void newRender(S renderState, PoseStack poseStack) {
poseStack.mulPose(Axis.YP.rotationDegrees(renderState.yRot));
poseStack.mulPose(Axis.ZP.rotationDegrees(-renderState.xRot));
poseStack.translate(0.0F, 0.375F, 0.0F);
}
private static <S extends MinecartRenderState> void oldRender(S renderState, PoseStack poseStack) {
double d = renderState.x;
double e = renderState.y;
double f = renderState.z;
float g = renderState.xRot;
float h = renderState.yRot;
if (renderState.posOnRail != null && renderState.frontPos != null && renderState.backPos != null) {
Vec3 vec3 = renderState.frontPos;
Vec3 vec32 = renderState.backPos;
poseStack.translate(renderState.posOnRail.x - d, (vec3.y + vec32.y) / 2.0 - e, renderState.posOnRail.z - f);
Vec3 vec33 = vec32.add(-vec3.x, -vec3.y, -vec3.z);
if (vec33.length() != 0.0) {
vec33 = vec33.normalize();
h = (float)(Math.atan2(vec33.z, vec33.x) * 180.0 / Math.PI);
g = (float)(Math.atan(vec33.y) * 73.0);
}
}
poseStack.translate(0.0F, 0.375F, 0.0F);
poseStack.mulPose(Axis.YP.rotationDegrees(180.0F - h));
poseStack.mulPose(Axis.ZP.rotationDegrees(-g));
}
public void extractRenderState(T abstractMinecart, S minecartRenderState, float f) {
super.extractRenderState(abstractMinecart, minecartRenderState, f);
if (abstractMinecart.getBehavior() instanceof NewMinecartBehavior newMinecartBehavior) {
newExtractState(abstractMinecart, newMinecartBehavior, minecartRenderState, f);
minecartRenderState.isNewRender = true;
} else if (abstractMinecart.getBehavior() instanceof OldMinecartBehavior oldMinecartBehavior) {
oldExtractState(abstractMinecart, oldMinecartBehavior, minecartRenderState, f);
minecartRenderState.isNewRender = false;
}
long l = abstractMinecart.getId() * 493286711L;
minecartRenderState.offsetSeed = l * l * 4392167121L + l * 98761L;
minecartRenderState.hurtTime = abstractMinecart.getHurtTime() - f;
minecartRenderState.hurtDir = abstractMinecart.getHurtDir();
minecartRenderState.damageTime = Math.max(abstractMinecart.getDamage() - f, 0.0F);
minecartRenderState.displayOffset = abstractMinecart.getDisplayOffset();
minecartRenderState.displayBlockState = abstractMinecart.getDisplayBlockState();
}
private static <T extends AbstractMinecart, S extends MinecartRenderState> void newExtractState(
T minecart, NewMinecartBehavior behavior, S renderState, float partialTick
) {
if (behavior.cartHasPosRotLerp()) {
renderState.renderPos = behavior.getCartLerpPosition(partialTick);
renderState.xRot = behavior.getCartLerpXRot(partialTick);
renderState.yRot = behavior.getCartLerpYRot(partialTick);
} else {
renderState.renderPos = null;
renderState.xRot = minecart.getXRot();
renderState.yRot = minecart.getYRot();
}
}
private static <T extends AbstractMinecart, S extends MinecartRenderState> void oldExtractState(
T minecart, OldMinecartBehavior behavior, S renderState, float partialTick
) {
float f = 0.3F;
renderState.xRot = minecart.getXRot(partialTick);
renderState.yRot = minecart.getYRot(partialTick);
double d = renderState.x;
double e = renderState.y;
double g = renderState.z;
Vec3 vec3 = behavior.getPos(d, e, g);
if (vec3 != null) {
renderState.posOnRail = vec3;
Vec3 vec32 = behavior.getPosOffs(d, e, g, 0.3F);
Vec3 vec33 = behavior.getPosOffs(d, e, g, -0.3F);
renderState.frontPos = (Vec3)Objects.requireNonNullElse(vec32, vec3);
renderState.backPos = (Vec3)Objects.requireNonNullElse(vec33, vec3);
} else {
renderState.posOnRail = null;
renderState.frontPos = null;
renderState.backPos = null;
}
}
protected void renderMinecartContents(S renderState, BlockState state, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight) {
this.blockRenderer.renderSingleBlock(state, poseStack, bufferSource, packedLight, OverlayTexture.NO_OVERLAY);
}
protected AABB getBoundingBoxForCulling(T abstractMinecart) {
AABB aABB = super.getBoundingBoxForCulling(abstractMinecart);
return !abstractMinecart.getDisplayBlockState().isAir() ? aABB.expandTowards(0.0, abstractMinecart.getDisplayOffset() * 0.75F / 16.0F, 0.0) : aABB;
}
public Vec3 getRenderOffset(S minecartRenderState) {
Vec3 vec3 = super.getRenderOffset(minecartRenderState);
return minecartRenderState.isNewRender && minecartRenderState.renderPos != null
? vec3.add(
minecartRenderState.renderPos.x - minecartRenderState.x,
minecartRenderState.renderPos.y - minecartRenderState.y,
minecartRenderState.renderPos.z - minecartRenderState.z
)
: vec3;
}
}