349 lines
14 KiB
Java
349 lines
14 KiB
Java
|
package net.minecraft.client.renderer.entity;
|
||
|
|
||
|
import com.google.common.collect.Lists;
|
||
|
import com.google.common.collect.ImmutableList.Builder;
|
||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||
|
import com.mojang.math.Axis;
|
||
|
import java.util.List;
|
||
|
import javax.annotation.Nullable;
|
||
|
import net.minecraft.ChatFormatting;
|
||
|
import net.minecraft.client.Minecraft;
|
||
|
import net.minecraft.client.model.EntityModel;
|
||
|
import net.minecraft.client.player.LocalPlayer;
|
||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||
|
import net.minecraft.client.renderer.RenderType;
|
||
|
import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer;
|
||
|
import net.minecraft.client.renderer.entity.layers.RenderLayer;
|
||
|
import net.minecraft.client.renderer.entity.state.HitboxRenderState;
|
||
|
import net.minecraft.client.renderer.entity.state.LivingEntityRenderState;
|
||
|
import net.minecraft.client.renderer.item.ItemModelResolver;
|
||
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||
|
import net.minecraft.core.Direction;
|
||
|
import net.minecraft.core.component.DataComponents;
|
||
|
import net.minecraft.resources.ResourceLocation;
|
||
|
import net.minecraft.util.ARGB;
|
||
|
import net.minecraft.util.Mth;
|
||
|
import net.minecraft.world.entity.EquipmentSlot;
|
||
|
import net.minecraft.world.entity.LivingEntity;
|
||
|
import net.minecraft.world.entity.Pose;
|
||
|
import net.minecraft.world.entity.player.Player;
|
||
|
import net.minecraft.world.entity.player.PlayerModelPart;
|
||
|
import net.minecraft.world.item.BlockItem;
|
||
|
import net.minecraft.world.item.ItemDisplayContext;
|
||
|
import net.minecraft.world.item.ItemStack;
|
||
|
import net.minecraft.world.item.Items;
|
||
|
import net.minecraft.world.level.block.AbstractSkullBlock;
|
||
|
import net.minecraft.world.phys.AABB;
|
||
|
import net.minecraft.world.scores.Team;
|
||
|
import net.minecraftforge.api.distmarker.Dist;
|
||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||
|
|
||
|
@OnlyIn(Dist.CLIENT)
|
||
|
public abstract class LivingEntityRenderer<T extends LivingEntity, S extends LivingEntityRenderState, M extends EntityModel<? super S>>
|
||
|
extends EntityRenderer<T, S>
|
||
|
implements RenderLayerParent<S, M> {
|
||
|
private static final float EYE_BED_OFFSET = 0.1F;
|
||
|
protected M model;
|
||
|
protected final ItemModelResolver itemModelResolver;
|
||
|
protected final List<RenderLayer<S, M>> layers = Lists.newArrayList();
|
||
|
|
||
|
public LivingEntityRenderer(EntityRendererProvider.Context p_174289_, M p_174290_, float p_174291_) {
|
||
|
super(p_174289_);
|
||
|
this.itemModelResolver = p_174289_.getItemModelResolver();
|
||
|
this.model = p_174290_;
|
||
|
this.shadowRadius = p_174291_;
|
||
|
}
|
||
|
|
||
|
protected final boolean addLayer(RenderLayer<S, M> p_115327_) {
|
||
|
return this.layers.add(p_115327_);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public M getModel() {
|
||
|
return this.model;
|
||
|
}
|
||
|
|
||
|
protected AABB getBoundingBoxForCulling(T p_361472_) {
|
||
|
AABB aabb = super.getBoundingBoxForCulling(p_361472_);
|
||
|
if (p_361472_.getItemBySlot(EquipmentSlot.HEAD).is(Items.DRAGON_HEAD)) {
|
||
|
float f = 0.5F;
|
||
|
return aabb.inflate(0.5, 0.5, 0.5);
|
||
|
} else {
|
||
|
return aabb;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void render(S p_364280_, PoseStack p_115311_, MultiBufferSource p_115312_, int p_115313_) {
|
||
|
p_115311_.pushPose();
|
||
|
if (p_364280_.hasPose(Pose.SLEEPING)) {
|
||
|
Direction direction = p_364280_.bedOrientation;
|
||
|
if (direction != null) {
|
||
|
float f = p_364280_.eyeHeight - 0.1F;
|
||
|
p_115311_.translate(-direction.getStepX() * f, 0.0F, -direction.getStepZ() * f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float f1 = p_364280_.scale;
|
||
|
p_115311_.scale(f1, f1, f1);
|
||
|
this.setupRotations(p_364280_, p_115311_, p_364280_.bodyRot, f1);
|
||
|
p_115311_.scale(-1.0F, -1.0F, 1.0F);
|
||
|
this.scale(p_364280_, p_115311_);
|
||
|
p_115311_.translate(0.0F, -1.501F, 0.0F);
|
||
|
this.model.setupAnim(p_364280_);
|
||
|
boolean flag1 = this.isBodyVisible(p_364280_);
|
||
|
boolean flag = !flag1 && !p_364280_.isInvisibleToPlayer;
|
||
|
RenderType rendertype = this.getRenderType(p_364280_, flag1, flag, p_364280_.appearsGlowing);
|
||
|
if (rendertype != null) {
|
||
|
VertexConsumer vertexconsumer = p_115312_.getBuffer(rendertype);
|
||
|
int i = getOverlayCoords(p_364280_, this.getWhiteOverlayProgress(p_364280_));
|
||
|
int j = flag ? 654311423 : -1;
|
||
|
int k = ARGB.multiply(j, this.getModelTint(p_364280_));
|
||
|
this.model.renderToBuffer(p_115311_, vertexconsumer, p_115313_, i, k);
|
||
|
}
|
||
|
|
||
|
if (this.shouldRenderLayers(p_364280_)) {
|
||
|
for (RenderLayer<S, M> renderlayer : this.layers) {
|
||
|
renderlayer.render(p_115311_, p_115312_, p_115313_, p_364280_, p_364280_.yRot, p_364280_.xRot);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
p_115311_.popPose();
|
||
|
super.render(p_364280_, p_115311_, p_115312_, p_115313_);
|
||
|
}
|
||
|
|
||
|
protected boolean shouldRenderLayers(S p_360804_) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
protected int getModelTint(S p_361319_) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
public abstract ResourceLocation getTextureLocation(S p_362468_);
|
||
|
|
||
|
@Nullable
|
||
|
protected RenderType getRenderType(S p_369777_, boolean p_115323_, boolean p_115324_, boolean p_115325_) {
|
||
|
ResourceLocation resourcelocation = this.getTextureLocation(p_369777_);
|
||
|
if (p_115324_) {
|
||
|
return RenderType.itemEntityTranslucentCull(resourcelocation);
|
||
|
} else if (p_115323_) {
|
||
|
return this.model.renderType(resourcelocation);
|
||
|
} else {
|
||
|
return p_115325_ ? RenderType.outline(resourcelocation) : null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static int getOverlayCoords(LivingEntityRenderState p_365259_, float p_115340_) {
|
||
|
return OverlayTexture.pack(OverlayTexture.u(p_115340_), OverlayTexture.v(p_365259_.hasRedOverlay));
|
||
|
}
|
||
|
|
||
|
protected boolean isBodyVisible(S p_363166_) {
|
||
|
return !p_363166_.isInvisible;
|
||
|
}
|
||
|
|
||
|
private static float sleepDirectionToRotation(Direction p_115329_) {
|
||
|
switch (p_115329_) {
|
||
|
case SOUTH:
|
||
|
return 90.0F;
|
||
|
case WEST:
|
||
|
return 0.0F;
|
||
|
case NORTH:
|
||
|
return 270.0F;
|
||
|
case EAST:
|
||
|
return 180.0F;
|
||
|
default:
|
||
|
return 0.0F;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected boolean isShaking(S p_361206_) {
|
||
|
return p_361206_.isFullyFrozen;
|
||
|
}
|
||
|
|
||
|
protected void setupRotations(S p_370120_, PoseStack p_115318_, float p_115319_, float p_115320_) {
|
||
|
if (this.isShaking(p_370120_)) {
|
||
|
p_115319_ += (float)(Math.cos(Mth.floor(p_370120_.ageInTicks) * 3.25F) * Math.PI * 0.4F);
|
||
|
}
|
||
|
|
||
|
if (!p_370120_.hasPose(Pose.SLEEPING)) {
|
||
|
p_115318_.mulPose(Axis.YP.rotationDegrees(180.0F - p_115319_));
|
||
|
}
|
||
|
|
||
|
if (p_370120_.deathTime > 0.0F) {
|
||
|
float f = (p_370120_.deathTime - 1.0F) / 20.0F * 1.6F;
|
||
|
f = Mth.sqrt(f);
|
||
|
if (f > 1.0F) {
|
||
|
f = 1.0F;
|
||
|
}
|
||
|
|
||
|
p_115318_.mulPose(Axis.ZP.rotationDegrees(f * this.getFlipDegrees()));
|
||
|
} else if (p_370120_.isAutoSpinAttack) {
|
||
|
p_115318_.mulPose(Axis.XP.rotationDegrees(-90.0F - p_370120_.xRot));
|
||
|
p_115318_.mulPose(Axis.YP.rotationDegrees(p_370120_.ageInTicks * -75.0F));
|
||
|
} else if (p_370120_.hasPose(Pose.SLEEPING)) {
|
||
|
Direction direction = p_370120_.bedOrientation;
|
||
|
float f1 = direction != null ? sleepDirectionToRotation(direction) : p_115319_;
|
||
|
p_115318_.mulPose(Axis.YP.rotationDegrees(f1));
|
||
|
p_115318_.mulPose(Axis.ZP.rotationDegrees(this.getFlipDegrees()));
|
||
|
p_115318_.mulPose(Axis.YP.rotationDegrees(270.0F));
|
||
|
} else if (p_370120_.isUpsideDown) {
|
||
|
p_115318_.translate(0.0F, (p_370120_.boundingBoxHeight + 0.1F) / p_115320_, 0.0F);
|
||
|
p_115318_.mulPose(Axis.ZP.rotationDegrees(180.0F));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected float getFlipDegrees() {
|
||
|
return 90.0F;
|
||
|
}
|
||
|
|
||
|
protected float getWhiteOverlayProgress(S p_367139_) {
|
||
|
return 0.0F;
|
||
|
}
|
||
|
|
||
|
protected void scale(S p_363445_, PoseStack p_115315_) {
|
||
|
}
|
||
|
|
||
|
protected boolean shouldShowName(T p_115333_, double p_365822_) {
|
||
|
if (p_115333_.isDiscrete()) {
|
||
|
float f = 32.0F;
|
||
|
if (p_365822_ >= 1024.0) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Minecraft minecraft = Minecraft.getInstance();
|
||
|
LocalPlayer localplayer = minecraft.player;
|
||
|
boolean flag = !p_115333_.isInvisibleTo(localplayer);
|
||
|
if (p_115333_ != localplayer) {
|
||
|
Team team = p_115333_.getTeam();
|
||
|
Team team1 = localplayer.getTeam();
|
||
|
if (team != null) {
|
||
|
Team.Visibility team$visibility = team.getNameTagVisibility();
|
||
|
switch (team$visibility) {
|
||
|
case ALWAYS:
|
||
|
return flag;
|
||
|
case NEVER:
|
||
|
return false;
|
||
|
case HIDE_FOR_OTHER_TEAMS:
|
||
|
return team1 == null ? flag : team.isAlliedTo(team1) && (team.canSeeFriendlyInvisibles() || flag);
|
||
|
case HIDE_FOR_OWN_TEAM:
|
||
|
return team1 == null ? flag : !team.isAlliedTo(team1) && flag;
|
||
|
default:
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Minecraft.renderNames() && p_115333_ != minecraft.getCameraEntity() && flag && !p_115333_.isVehicle();
|
||
|
}
|
||
|
|
||
|
public static boolean isEntityUpsideDown(LivingEntity p_194454_) {
|
||
|
if (p_194454_ instanceof Player || p_194454_.hasCustomName()) {
|
||
|
String s = ChatFormatting.stripFormatting(p_194454_.getName().getString());
|
||
|
if ("Dinnerbone".equals(s) || "Grumm".equals(s)) {
|
||
|
return !(p_194454_ instanceof Player player && !player.isModelPartShown(PlayerModelPart.CAPE));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
protected float getShadowRadius(S p_363803_) {
|
||
|
return super.getShadowRadius(p_363803_) * p_363803_.scale;
|
||
|
}
|
||
|
|
||
|
public void extractRenderState(T p_368665_, S p_363057_, float p_364497_) {
|
||
|
super.extractRenderState(p_368665_, p_363057_, p_364497_);
|
||
|
float f = Mth.rotLerp(p_364497_, p_368665_.yHeadRotO, p_368665_.yHeadRot);
|
||
|
p_363057_.bodyRot = solveBodyRot(p_368665_, f, p_364497_);
|
||
|
p_363057_.yRot = Mth.wrapDegrees(f - p_363057_.bodyRot);
|
||
|
p_363057_.xRot = p_368665_.getXRot(p_364497_);
|
||
|
p_363057_.customName = p_368665_.getCustomName();
|
||
|
p_363057_.isUpsideDown = isEntityUpsideDown(p_368665_);
|
||
|
if (p_363057_.isUpsideDown) {
|
||
|
p_363057_.xRot *= -1.0F;
|
||
|
p_363057_.yRot *= -1.0F;
|
||
|
}
|
||
|
|
||
|
if (!p_368665_.isPassenger() && p_368665_.isAlive()) {
|
||
|
p_363057_.walkAnimationPos = p_368665_.walkAnimation.position(p_364497_);
|
||
|
p_363057_.walkAnimationSpeed = p_368665_.walkAnimation.speed(p_364497_);
|
||
|
} else {
|
||
|
p_363057_.walkAnimationPos = 0.0F;
|
||
|
p_363057_.walkAnimationSpeed = 0.0F;
|
||
|
}
|
||
|
|
||
|
if (p_368665_.getVehicle() instanceof LivingEntity livingentity) {
|
||
|
p_363057_.wornHeadAnimationPos = livingentity.walkAnimation.position(p_364497_);
|
||
|
} else {
|
||
|
p_363057_.wornHeadAnimationPos = p_363057_.walkAnimationPos;
|
||
|
}
|
||
|
|
||
|
p_363057_.scale = p_368665_.getScale();
|
||
|
p_363057_.ageScale = p_368665_.getAgeScale();
|
||
|
p_363057_.pose = p_368665_.getPose();
|
||
|
p_363057_.bedOrientation = p_368665_.getBedOrientation();
|
||
|
if (p_363057_.bedOrientation != null) {
|
||
|
p_363057_.eyeHeight = p_368665_.getEyeHeight(Pose.STANDING);
|
||
|
}
|
||
|
|
||
|
p_363057_.isFullyFrozen = p_368665_.isFullyFrozen();
|
||
|
p_363057_.isBaby = p_368665_.isBaby();
|
||
|
p_363057_.isInWater = p_368665_.isInWater();
|
||
|
p_363057_.isAutoSpinAttack = p_368665_.isAutoSpinAttack();
|
||
|
p_363057_.hasRedOverlay = p_368665_.hurtTime > 0 || p_368665_.deathTime > 0;
|
||
|
ItemStack itemstack = p_368665_.getItemBySlot(EquipmentSlot.HEAD);
|
||
|
if (itemstack.getItem() instanceof BlockItem blockitem && blockitem.getBlock() instanceof AbstractSkullBlock abstractskullblock) {
|
||
|
p_363057_.wornHeadType = abstractskullblock.getType();
|
||
|
p_363057_.wornHeadProfile = itemstack.get(DataComponents.PROFILE);
|
||
|
p_363057_.headItem.clear();
|
||
|
} else {
|
||
|
p_363057_.wornHeadType = null;
|
||
|
p_363057_.wornHeadProfile = null;
|
||
|
if (!HumanoidArmorLayer.shouldRender(itemstack, EquipmentSlot.HEAD)) {
|
||
|
this.itemModelResolver.updateForLiving(p_363057_.headItem, itemstack, ItemDisplayContext.HEAD, p_368665_);
|
||
|
} else {
|
||
|
p_363057_.headItem.clear();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
p_363057_.deathTime = p_368665_.deathTime > 0 ? p_368665_.deathTime + p_364497_ : 0.0F;
|
||
|
Minecraft minecraft = Minecraft.getInstance();
|
||
|
p_363057_.isInvisibleToPlayer = p_363057_.isInvisible && p_368665_.isInvisibleTo(minecraft.player);
|
||
|
p_363057_.appearsGlowing = minecraft.shouldEntityAppearGlowing(p_368665_);
|
||
|
}
|
||
|
|
||
|
protected void extractAdditionalHitboxes(T p_392957_, Builder<HitboxRenderState> p_396936_, float p_397822_) {
|
||
|
AABB aabb = p_392957_.getBoundingBox();
|
||
|
float f = 0.01F;
|
||
|
HitboxRenderState hitboxrenderstate = new HitboxRenderState(
|
||
|
aabb.minX - p_392957_.getX(),
|
||
|
p_392957_.getEyeHeight() - 0.01F,
|
||
|
aabb.minZ - p_392957_.getZ(),
|
||
|
aabb.maxX - p_392957_.getX(),
|
||
|
p_392957_.getEyeHeight() + 0.01F,
|
||
|
aabb.maxZ - p_392957_.getZ(),
|
||
|
1.0F,
|
||
|
0.0F,
|
||
|
0.0F
|
||
|
);
|
||
|
p_396936_.add(hitboxrenderstate);
|
||
|
}
|
||
|
|
||
|
private static float solveBodyRot(LivingEntity p_367822_, float p_362662_, float p_362007_) {
|
||
|
if (p_367822_.getVehicle() instanceof LivingEntity livingentity) {
|
||
|
float f2 = Mth.rotLerp(p_362007_, livingentity.yBodyRotO, livingentity.yBodyRot);
|
||
|
float f = 85.0F;
|
||
|
float f1 = Mth.clamp(Mth.wrapDegrees(p_362662_ - f2), -85.0F, 85.0F);
|
||
|
f2 = p_362662_ - f1;
|
||
|
if (Math.abs(f1) > 50.0F) {
|
||
|
f2 += f1 * 0.2F;
|
||
|
}
|
||
|
|
||
|
return f2;
|
||
|
} else {
|
||
|
return Mth.rotLerp(p_362007_, p_367822_.yBodyRotO, p_367822_.yBodyRot);
|
||
|
}
|
||
|
}
|
||
|
}
|