LivingEntityRenderer.java
net.minecraft.client.renderer.entity.LivingEntityRenderer
信息
- 全限定名:net.minecraft.client.renderer.entity.LivingEntityRenderer
- 类型:public abstract class
- 包:net.minecraft.client.renderer.entity
- 源码路径:src/main/java/net/minecraft/client/renderer/entity/LivingEntityRenderer.java
- 起始行号:L40
- 继承:EntityRenderer<T,S>
- 实现:RenderLayerParent<S,M>
- 职责:
TODO
字段/常量
-
EYE_BED_OFFSET- 类型:
float - 修饰符:
private static final - 源码定位:
L43 - 说明:
TODO
- 类型:
-
model- 类型:
M - 修饰符:
protected - 源码定位:
L44 - 说明:
TODO
- 类型:
-
itemModelResolver- 类型:
ItemModelResolver - 修饰符:
protected final - 源码定位:
L45 - 说明:
TODO
- 类型:
-
layers- 类型:
List<RenderLayer<S,M>> - 修饰符:
protected final - 源码定位:
L46 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
public LivingEntityRenderer(EntityRendererProvider.Context context, M model, float shadow) @ L48
- 构造器名:LivingEntityRenderer
- 源码定位:L48
- 修饰符:public
参数:
- context: EntityRendererProvider.Context
- model: M
- shadow: float
说明:
TODO
方法
下面的方法块按源码顺序生成。
protected final boolean addLayer(RenderLayer<S,M> layer) @ L55
- 方法名:addLayer
- 源码定位:L55
- 返回类型:boolean
- 修饰符:protected final
参数:
- layer: RenderLayer<S,M>
说明:
TODO
public M getModel() @ L59
- 方法名:getModel
- 源码定位:L59
- 返回类型:M
- 修饰符:public
参数:
- 无
说明:
TODO
protected AABB getBoundingBoxForCulling(T entity) @ L64
- 方法名:getBoundingBoxForCulling
- 源码定位:L64
- 返回类型:AABB
- 修饰符:protected
参数:
- entity: T
说明:
TODO
public void submit(S state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState camera) @ L74
- 方法名:submit
- 源码定位:L74
- 返回类型:void
- 修饰符:public
参数:
- state: S
- poseStack: PoseStack
- submitNodeCollector: SubmitNodeCollector
- camera: CameraRenderState
说明:
TODO
protected boolean shouldRenderLayers(S state) @ L114
- 方法名:shouldRenderLayers
- 源码定位:L114
- 返回类型:boolean
- 修饰符:protected
参数:
- state: S
说明:
TODO
protected int getModelTint(S state) @ L118
- 方法名:getModelTint
- 源码定位:L118
- 返回类型:int
- 修饰符:protected
参数:
- state: S
说明:
TODO
public abstract Identifier getTextureLocation(S state) @ L122
- 方法名:getTextureLocation
- 源码定位:L122
- 返回类型:Identifier
- 修饰符:public abstract
参数:
- state: S
说明:
TODO
protected RenderType getRenderType(S state, boolean isBodyVisible, boolean forceTransparent, boolean appearGlowing) @ L124
- 方法名:getRenderType
- 源码定位:L124
- 返回类型:RenderType
- 修饰符:protected
参数:
- state: S
- isBodyVisible: boolean
- forceTransparent: boolean
- appearGlowing: boolean
说明:
TODO
public static int getOverlayCoords(LivingEntityRenderState state, float whiteOverlayProgress) @ L135
- 方法名:getOverlayCoords
- 源码定位:L135
- 返回类型:int
- 修饰符:public static
参数:
- state: LivingEntityRenderState
- whiteOverlayProgress: float
说明:
TODO
protected boolean isBodyVisible(S state) @ L139
- 方法名:isBodyVisible
- 源码定位:L139
- 返回类型:boolean
- 修饰符:protected
参数:
- state: S
说明:
TODO
private static float sleepDirectionToRotation(Direction direction) @ L143
- 方法名:sleepDirectionToRotation
- 源码定位:L143
- 返回类型:float
- 修饰符:private static
参数:
- direction: Direction
说明:
TODO
protected boolean isShaking(S state) @ L158
- 方法名:isShaking
- 源码定位:L158
- 返回类型:boolean
- 修饰符:protected
参数:
- state: S
说明:
TODO
protected void setupRotations(S state, PoseStack poseStack, float bodyRot, float entityScale) @ L162
- 方法名:setupRotations
- 源码定位:L162
- 返回类型:void
- 修饰符:protected
参数:
- state: S
- poseStack: PoseStack
- bodyRot: float
- entityScale: float
说明:
TODO
protected float getFlipDegrees() @ L194
- 方法名:getFlipDegrees
- 源码定位:L194
- 返回类型:float
- 修饰符:protected
参数:
- 无
说明:
TODO
protected float getWhiteOverlayProgress(S state) @ L198
- 方法名:getWhiteOverlayProgress
- 源码定位:L198
- 返回类型:float
- 修饰符:protected
参数:
- state: S
说明:
TODO
protected void scale(S state, PoseStack poseStack) @ L202
- 方法名:scale
- 源码定位:L202
- 返回类型:void
- 修饰符:protected
参数:
- state: S
- poseStack: PoseStack
说明:
TODO
protected boolean shouldShowName(T entity, double distanceToCameraSq) @ L205
- 方法名:shouldShowName
- 源码定位:L205
- 返回类型:boolean
- 修饰符:protected
参数:
- entity: T
- distanceToCameraSq: double
说明:
TODO
public boolean isEntityUpsideDown(T mob) @ L239
- 方法名:isEntityUpsideDown
- 源码定位:L239
- 返回类型:boolean
- 修饰符:public
参数:
- mob: T
说明:
TODO
protected static boolean isUpsideDownName(String name) @ L244
- 方法名:isUpsideDownName
- 源码定位:L244
- 返回类型:boolean
- 修饰符:protected static
参数:
- name: String
说明:
TODO
protected float getShadowRadius(S state) @ L248
- 方法名:getShadowRadius
- 源码定位:L248
- 返回类型:float
- 修饰符:protected
参数:
- state: S
说明:
TODO
public void extractRenderState(T entity, S state, float partialTicks) @ L252
- 方法名:extractRenderState
- 源码定位:L252
- 返回类型:void
- 修饰符:public
参数:
- entity: T
- state: S
- partialTicks: float
说明:
TODO
private static float solveBodyRot(LivingEntity entity, float headRot, float partialTicks) @ L312
- 方法名:solveBodyRot
- 源码定位:L312
- 返回类型:float
- 修饰符:private static
参数:
- entity: LivingEntity
- headRot: float
- partialTicks: float
说明:
TODO
代码
@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 context, M model, float shadow) {
super(context);
this.itemModelResolver = context.getItemModelResolver();
this.model = model;
this.shadowRadius = shadow;
}
protected final boolean addLayer(RenderLayer<S, M> layer) {
return this.layers.add(layer);
}
@Override
public M getModel() {
return this.model;
}
protected AABB getBoundingBoxForCulling(T entity) {
AABB aabb = super.getBoundingBoxForCulling(entity);
if (entity.getItemBySlot(EquipmentSlot.HEAD).is(Items.DRAGON_HEAD)) {
float extraSize = 0.5F;
return aabb.inflate(0.5, 0.5, 0.5);
} else {
return aabb;
}
}
public void submit(S state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState camera) {
poseStack.pushPose();
if (state.hasPose(Pose.SLEEPING)) {
Direction bedOrientation = state.bedOrientation;
if (bedOrientation != null) {
float headOffset = state.eyeHeight - 0.1F;
poseStack.translate(-bedOrientation.getStepX() * headOffset, 0.0F, -bedOrientation.getStepZ() * headOffset);
}
}
float scale = state.scale;
poseStack.scale(scale, scale, scale);
this.setupRotations(state, poseStack, state.bodyRot, scale);
poseStack.scale(-1.0F, -1.0F, 1.0F);
this.scale(state, poseStack);
poseStack.translate(0.0F, -1.501F, 0.0F);
boolean isBodyVisible = this.isBodyVisible(state);
boolean forceTransparent = !isBodyVisible && !state.isInvisibleToPlayer;
RenderType renderType = this.getRenderType(state, isBodyVisible, forceTransparent, state.appearsGlowing());
if (renderType != null) {
int overlayCoords = getOverlayCoords(state, this.getWhiteOverlayProgress(state));
int baseColor = forceTransparent ? 654311423 : -1;
int tintedColor = ARGB.multiply(baseColor, this.getModelTint(state));
submitNodeCollector.submitModel(
this.model, state, poseStack, renderType, state.lightCoords, overlayCoords, tintedColor, null, state.outlineColor, null
);
}
if (this.shouldRenderLayers(state) && !this.layers.isEmpty()) {
this.model.setupAnim(state);
for (RenderLayer<S, M> layer : this.layers) {
layer.submit(poseStack, submitNodeCollector, state.lightCoords, state, state.yRot, state.xRot);
}
}
poseStack.popPose();
super.submit(state, poseStack, submitNodeCollector, camera);
}
protected boolean shouldRenderLayers(S state) {
return true;
}
protected int getModelTint(S state) {
return -1;
}
public abstract Identifier getTextureLocation(final S state);
protected @Nullable RenderType getRenderType(S state, boolean isBodyVisible, boolean forceTransparent, boolean appearGlowing) {
Identifier texture = this.getTextureLocation(state);
if (forceTransparent) {
return RenderTypes.entityTranslucentCullItemTarget(texture);
} else if (isBodyVisible) {
return this.model.renderType(texture);
} else {
return appearGlowing ? RenderTypes.outline(texture) : null;
}
}
public static int getOverlayCoords(LivingEntityRenderState state, float whiteOverlayProgress) {
return OverlayTexture.pack(OverlayTexture.u(whiteOverlayProgress), OverlayTexture.v(state.hasRedOverlay));
}
protected boolean isBodyVisible(S state) {
return !state.isInvisible;
}
private static float sleepDirectionToRotation(Direction direction) {
switch (direction) {
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 state) {
return state.isFullyFrozen;
}
protected void setupRotations(S state, PoseStack poseStack, float bodyRot, float entityScale) {
if (this.isShaking(state)) {
bodyRot += (float)(Math.cos(Mth.floor(state.ageInTicks) * 3.25F) * Math.PI * 0.4F);
}
if (!state.hasPose(Pose.SLEEPING)) {
poseStack.mulPose(Axis.YP.rotationDegrees(180.0F - bodyRot));
}
if (state.deathTime > 0.0F) {
float fall = (state.deathTime - 1.0F) / 20.0F * 1.6F;
fall = Mth.sqrt(fall);
if (fall > 1.0F) {
fall = 1.0F;
}
poseStack.mulPose(Axis.ZP.rotationDegrees(fall * this.getFlipDegrees()));
} else if (state.isAutoSpinAttack) {
poseStack.mulPose(Axis.XP.rotationDegrees(-90.0F - state.xRot));
poseStack.mulPose(Axis.YP.rotationDegrees(state.ageInTicks * -75.0F));
} else if (state.hasPose(Pose.SLEEPING)) {
Direction bedOrientation = state.bedOrientation;
float angle = bedOrientation != null ? sleepDirectionToRotation(bedOrientation) : bodyRot;
poseStack.mulPose(Axis.YP.rotationDegrees(angle));
poseStack.mulPose(Axis.ZP.rotationDegrees(this.getFlipDegrees()));
poseStack.mulPose(Axis.YP.rotationDegrees(270.0F));
} else if (state.isUpsideDown) {
poseStack.translate(0.0F, (state.boundingBoxHeight + 0.1F) / entityScale, 0.0F);
poseStack.mulPose(Axis.ZP.rotationDegrees(180.0F));
}
}
protected float getFlipDegrees() {
return 90.0F;
}
protected float getWhiteOverlayProgress(S state) {
return 0.0F;
}
protected void scale(S state, PoseStack poseStack) {
}
protected boolean shouldShowName(T entity, double distanceToCameraSq) {
if (entity.isDiscrete()) {
float maxDist = 32.0F;
if (distanceToCameraSq >= 1024.0) {
return false;
}
}
Minecraft minecraft = Minecraft.getInstance();
LocalPlayer player = minecraft.player;
boolean isVisibleToPlayer = !entity.isInvisibleTo(player);
if (entity != player) {
Team team = entity.getTeam();
Team myTeam = player.getTeam();
if (team != null) {
Team.Visibility visibility = team.getNameTagVisibility();
switch (visibility) {
case ALWAYS:
return isVisibleToPlayer;
case NEVER:
return false;
case HIDE_FOR_OTHER_TEAMS:
return myTeam == null ? isVisibleToPlayer : team.isAlliedTo(myTeam) && (team.canSeeFriendlyInvisibles() || isVisibleToPlayer);
case HIDE_FOR_OWN_TEAM:
return myTeam == null ? isVisibleToPlayer : !team.isAlliedTo(myTeam) && isVisibleToPlayer;
default:
return true;
}
}
}
return Minecraft.renderNames() && entity != minecraft.getCameraEntity() && isVisibleToPlayer && !entity.isVehicle();
}
public boolean isEntityUpsideDown(T mob) {
Component customName = mob.getCustomName();
return customName != null && isUpsideDownName(customName.getString());
}
protected static boolean isUpsideDownName(String name) {
return "Dinnerbone".equals(name) || "Grumm".equals(name);
}
protected float getShadowRadius(S state) {
return super.getShadowRadius(state) * state.scale;
}
public void extractRenderState(T entity, S state, float partialTicks) {
super.extractRenderState(entity, state, partialTicks);
float headRot = Mth.rotLerp(partialTicks, entity.yHeadRotO, entity.yHeadRot);
state.bodyRot = solveBodyRot(entity, headRot, partialTicks);
state.yRot = Mth.wrapDegrees(headRot - state.bodyRot);
state.xRot = entity.getXRot(partialTicks);
state.isUpsideDown = this.isEntityUpsideDown(entity);
if (state.isUpsideDown) {
state.xRot *= -1.0F;
state.yRot *= -1.0F;
}
if (!entity.isPassenger() && entity.isAlive()) {
state.walkAnimationPos = entity.walkAnimation.position(partialTicks);
state.walkAnimationSpeed = entity.walkAnimation.speed(partialTicks);
} else {
state.walkAnimationPos = 0.0F;
state.walkAnimationSpeed = 0.0F;
}
if (entity.getVehicle() instanceof LivingEntity vehicle) {
state.wornHeadAnimationPos = vehicle.walkAnimation.position(partialTicks);
} else {
state.wornHeadAnimationPos = state.walkAnimationPos;
}
state.scale = entity.getScale();
state.ageScale = entity.getAgeScale();
state.pose = entity.getPose();
state.bedOrientation = entity.getBedOrientation();
if (state.bedOrientation != null) {
state.eyeHeight = entity.getEyeHeight(Pose.STANDING);
}
state.isFullyFrozen = entity.isFullyFrozen();
state.isBaby = entity.isBaby();
state.isInWater = entity.isInWater();
state.isAutoSpinAttack = entity.isAutoSpinAttack();
state.ticksSinceKineticHitFeedback = entity.getTicksSinceLastKineticHitFeedback(partialTicks);
state.hasRedOverlay = entity.hurtTime > 0 || entity.deathTime > 0;
ItemStack headItem = entity.getItemBySlot(EquipmentSlot.HEAD);
if (headItem.getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof AbstractSkullBlock skullBlock) {
state.wornHeadType = skullBlock.getType();
state.wornHeadProfile = headItem.get(DataComponents.PROFILE);
state.headItem.clear();
} else {
state.wornHeadType = null;
state.wornHeadProfile = null;
if (!HumanoidArmorLayer.shouldRender(headItem, EquipmentSlot.HEAD)) {
this.itemModelResolver.updateForLiving(state.headItem, headItem, ItemDisplayContext.HEAD, entity);
} else {
state.headItem.clear();
}
}
state.deathTime = entity.deathTime > 0 ? entity.deathTime + partialTicks : 0.0F;
Minecraft minecraft = Minecraft.getInstance();
state.isInvisibleToPlayer = state.isInvisible && entity.isInvisibleTo(minecraft.player);
}
private static float solveBodyRot(LivingEntity entity, float headRot, float partialTicks) {
if (entity.getVehicle() instanceof LivingEntity riding) {
float bodyRot = Mth.rotLerp(partialTicks, riding.yBodyRotO, riding.yBodyRot);
float maxHeadDiff = 85.0F;
float headDiff = Mth.clamp(Mth.wrapDegrees(headRot - bodyRot), -85.0F, 85.0F);
bodyRot = headRot - headDiff;
if (Math.abs(headDiff) > 50.0F) {
bodyRot += headDiff * 0.2F;
}
return bodyRot;
} else {
return Mth.rotLerp(partialTicks, entity.yBodyRotO, entity.yBodyRot);
}
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Minecraft.getInstance(), Minecraft.renderNames()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
继承
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
实现
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
HumanoidArmorLayer.shouldRender()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
字段
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
RenderTypes.entityTranslucentCullItemTarget(), RenderTypes.outline()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
OverlayTexture.pack(), OverlayTexture.u(), OverlayTexture.v()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
返回值
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ARGB.multiply()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.clamp(), Mth.floor(), Mth.rotLerp(), Mth.sqrt(), Mth.wrapDegrees()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
返回值
- 引用位置: