189 lines
11 KiB
Java
189 lines
11 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* org.joml.Quaternionf
|
|
* org.joml.Quaternionfc
|
|
* org.joml.Vector3f
|
|
*/
|
|
package net.minecraft.client.renderer.entity;
|
|
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import com.mojang.math.Axis;
|
|
import net.minecraft.client.model.dragon.EnderDragonModel;
|
|
import net.minecraft.client.model.geom.ModelLayers;
|
|
import net.minecraft.client.renderer.SubmitNodeCollector;
|
|
import net.minecraft.client.renderer.entity.EndCrystalRenderer;
|
|
import net.minecraft.client.renderer.entity.EntityRenderer;
|
|
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
|
import net.minecraft.client.renderer.entity.state.EnderDragonRenderState;
|
|
import net.minecraft.client.renderer.rendertype.RenderType;
|
|
import net.minecraft.client.renderer.rendertype.RenderTypes;
|
|
import net.minecraft.client.renderer.state.CameraRenderState;
|
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.resources.Identifier;
|
|
import net.minecraft.util.ARGB;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
|
|
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
|
|
import net.minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstance;
|
|
import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase;
|
|
import net.minecraft.world.level.levelgen.Heightmap;
|
|
import net.minecraft.world.level.levelgen.feature.EndPodiumFeature;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.joml.Quaternionf;
|
|
import org.joml.Quaternionfc;
|
|
import org.joml.Vector3f;
|
|
|
|
public class EnderDragonRenderer
|
|
extends EntityRenderer<EnderDragon, EnderDragonRenderState> {
|
|
public static final Identifier CRYSTAL_BEAM_LOCATION = Identifier.withDefaultNamespace("textures/entity/end_crystal/end_crystal_beam.png");
|
|
private static final Identifier DRAGON_EXPLODING_LOCATION = Identifier.withDefaultNamespace("textures/entity/enderdragon/dragon_exploding.png");
|
|
private static final Identifier DRAGON_LOCATION = Identifier.withDefaultNamespace("textures/entity/enderdragon/dragon.png");
|
|
private static final Identifier DRAGON_EYES_LOCATION = Identifier.withDefaultNamespace("textures/entity/enderdragon/dragon_eyes.png");
|
|
private static final RenderType RENDER_TYPE = RenderTypes.entityCutoutNoCull(DRAGON_LOCATION);
|
|
private static final RenderType DECAL = RenderTypes.entityDecal(DRAGON_LOCATION);
|
|
private static final RenderType EYES = RenderTypes.eyes(DRAGON_EYES_LOCATION);
|
|
private static final RenderType BEAM = RenderTypes.entitySmoothCutout(CRYSTAL_BEAM_LOCATION);
|
|
private static final float HALF_SQRT_3 = (float)(Math.sqrt(3.0) / 2.0);
|
|
private final EnderDragonModel model;
|
|
|
|
public EnderDragonRenderer(EntityRendererProvider.Context context) {
|
|
super(context);
|
|
this.shadowRadius = 0.5f;
|
|
this.model = new EnderDragonModel(context.bakeLayer(ModelLayers.ENDER_DRAGON));
|
|
}
|
|
|
|
@Override
|
|
public void submit(EnderDragonRenderState state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState camera) {
|
|
poseStack.pushPose();
|
|
float yr = state.getHistoricalPos(7).yRot();
|
|
float rot2 = (float)(state.getHistoricalPos(5).y() - state.getHistoricalPos(10).y());
|
|
poseStack.mulPose((Quaternionfc)Axis.YP.rotationDegrees(-yr));
|
|
poseStack.mulPose((Quaternionfc)Axis.XP.rotationDegrees(rot2 * 10.0f));
|
|
poseStack.translate(0.0f, 0.0f, 1.0f);
|
|
poseStack.scale(-1.0f, -1.0f, 1.0f);
|
|
poseStack.translate(0.0f, -1.501f, 0.0f);
|
|
int overlayCoords = OverlayTexture.pack(0.0f, state.hasRedOverlay);
|
|
if (state.deathTime > 0.0f) {
|
|
int color = ARGB.white(state.deathTime / 200.0f);
|
|
submitNodeCollector.order(0).submitModel(this.model, state, poseStack, RenderTypes.dragonExplosionAlpha(DRAGON_EXPLODING_LOCATION), state.lightCoords, OverlayTexture.NO_OVERLAY, color, null, state.outlineColor, null);
|
|
submitNodeCollector.order(1).submitModel(this.model, state, poseStack, DECAL, state.lightCoords, overlayCoords, -1, null, state.outlineColor, null);
|
|
} else {
|
|
submitNodeCollector.order(0).submitModel(this.model, state, poseStack, RENDER_TYPE, state.lightCoords, overlayCoords, -1, null, state.outlineColor, null);
|
|
}
|
|
submitNodeCollector.submitModel(this.model, state, poseStack, EYES, state.lightCoords, OverlayTexture.NO_OVERLAY, state.outlineColor, null);
|
|
if (state.deathTime > 0.0f) {
|
|
float deathTime = state.deathTime / 200.0f;
|
|
poseStack.pushPose();
|
|
poseStack.translate(0.0f, -1.0f, -2.0f);
|
|
EnderDragonRenderer.submitRays(poseStack, deathTime, submitNodeCollector, RenderTypes.dragonRays());
|
|
EnderDragonRenderer.submitRays(poseStack, deathTime, submitNodeCollector, RenderTypes.dragonRaysDepth());
|
|
poseStack.popPose();
|
|
}
|
|
poseStack.popPose();
|
|
if (state.beamOffset != null) {
|
|
EnderDragonRenderer.submitCrystalBeams((float)state.beamOffset.x, (float)state.beamOffset.y, (float)state.beamOffset.z, state.ageInTicks, poseStack, submitNodeCollector, state.lightCoords);
|
|
}
|
|
super.submit(state, poseStack, submitNodeCollector, camera);
|
|
}
|
|
|
|
private static void submitRays(PoseStack poseStack, float deathTime, SubmitNodeCollector submitNodeCollector, RenderType renderType) {
|
|
submitNodeCollector.submitCustomGeometry(poseStack, renderType, (pose, buffer) -> {
|
|
float overDrive = Math.min(deathTime > 0.8f ? (deathTime - 0.8f) / 0.2f : 0.0f, 1.0f);
|
|
int innerColor = ARGB.colorFromFloat(1.0f - overDrive, 1.0f, 1.0f, 1.0f);
|
|
int outerColor = 0xFF00FF;
|
|
RandomSource random = RandomSource.create(432L);
|
|
Vector3f origin = new Vector3f();
|
|
Vector3f outerLeft = new Vector3f();
|
|
Vector3f outerRight = new Vector3f();
|
|
Vector3f outerBottom = new Vector3f();
|
|
Quaternionf rayRotation = new Quaternionf();
|
|
int rayCount = Mth.floor((deathTime + deathTime * deathTime) / 2.0f * 60.0f);
|
|
for (int i = 0; i < rayCount; ++i) {
|
|
rayRotation.rotationXYZ(random.nextFloat() * ((float)Math.PI * 2), random.nextFloat() * ((float)Math.PI * 2), random.nextFloat() * ((float)Math.PI * 2)).rotateXYZ(random.nextFloat() * ((float)Math.PI * 2), random.nextFloat() * ((float)Math.PI * 2), random.nextFloat() * ((float)Math.PI * 2) + deathTime * 1.5707964f);
|
|
pose.rotate((Quaternionfc)rayRotation);
|
|
float length = random.nextFloat() * 20.0f + 5.0f + overDrive * 10.0f;
|
|
float width = random.nextFloat() * 2.0f + 1.0f + overDrive * 2.0f;
|
|
outerLeft.set(-HALF_SQRT_3 * width, length, -0.5f * width);
|
|
outerRight.set(HALF_SQRT_3 * width, length, -0.5f * width);
|
|
outerBottom.set(0.0f, length, width);
|
|
buffer.addVertex(pose, origin).setColor(innerColor);
|
|
buffer.addVertex(pose, outerLeft).setColor(0xFF00FF);
|
|
buffer.addVertex(pose, outerRight).setColor(0xFF00FF);
|
|
buffer.addVertex(pose, origin).setColor(innerColor);
|
|
buffer.addVertex(pose, outerRight).setColor(0xFF00FF);
|
|
buffer.addVertex(pose, outerBottom).setColor(0xFF00FF);
|
|
buffer.addVertex(pose, origin).setColor(innerColor);
|
|
buffer.addVertex(pose, outerBottom).setColor(0xFF00FF);
|
|
buffer.addVertex(pose, outerLeft).setColor(0xFF00FF);
|
|
}
|
|
});
|
|
}
|
|
|
|
public static void submitCrystalBeams(float deltaX, float deltaY, float deltaZ, float timeInTicks, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int lightCoords) {
|
|
float horizontalLength = Mth.sqrt(deltaX * deltaX + deltaZ * deltaZ);
|
|
float length = Mth.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);
|
|
poseStack.pushPose();
|
|
poseStack.translate(0.0f, 2.0f, 0.0f);
|
|
poseStack.mulPose((Quaternionfc)Axis.YP.rotation((float)(-Math.atan2(deltaZ, deltaX)) - 1.5707964f));
|
|
poseStack.mulPose((Quaternionfc)Axis.XP.rotation((float)(-Math.atan2(horizontalLength, deltaY)) - 1.5707964f));
|
|
float v0 = 0.0f - timeInTicks * 0.01f;
|
|
float v1 = length / 32.0f - timeInTicks * 0.01f;
|
|
submitNodeCollector.submitCustomGeometry(poseStack, BEAM, (pose, buffer) -> {
|
|
int steps = 8;
|
|
float lastSin = 0.0f;
|
|
float lastCos = 0.75f;
|
|
float lastU = 0.0f;
|
|
for (int i = 1; i <= 8; ++i) {
|
|
float sin = Mth.sin((float)i * ((float)Math.PI * 2) / 8.0f) * 0.75f;
|
|
float cos = Mth.cos((float)i * ((float)Math.PI * 2) / 8.0f) * 0.75f;
|
|
float u = (float)i / 8.0f;
|
|
buffer.addVertex(pose, lastSin * 0.2f, lastCos * 0.2f, 0.0f).setColor(-16777216).setUv(lastU, v0).setOverlay(OverlayTexture.NO_OVERLAY).setLight(lightCoords).setNormal(pose, 0.0f, -1.0f, 0.0f);
|
|
buffer.addVertex(pose, lastSin, lastCos, length).setColor(-1).setUv(lastU, v1).setOverlay(OverlayTexture.NO_OVERLAY).setLight(lightCoords).setNormal(pose, 0.0f, -1.0f, 0.0f);
|
|
buffer.addVertex(pose, sin, cos, length).setColor(-1).setUv(u, v1).setOverlay(OverlayTexture.NO_OVERLAY).setLight(lightCoords).setNormal(pose, 0.0f, -1.0f, 0.0f);
|
|
buffer.addVertex(pose, sin * 0.2f, cos * 0.2f, 0.0f).setColor(-16777216).setUv(u, v0).setOverlay(OverlayTexture.NO_OVERLAY).setLight(lightCoords).setNormal(pose, 0.0f, -1.0f, 0.0f);
|
|
lastSin = sin;
|
|
lastCos = cos;
|
|
lastU = u;
|
|
}
|
|
});
|
|
poseStack.popPose();
|
|
}
|
|
|
|
@Override
|
|
public EnderDragonRenderState createRenderState() {
|
|
return new EnderDragonRenderState();
|
|
}
|
|
|
|
@Override
|
|
public void extractRenderState(EnderDragon entity, EnderDragonRenderState state, float partialTicks) {
|
|
super.extractRenderState(entity, state, partialTicks);
|
|
state.flapTime = Mth.lerp(partialTicks, entity.oFlapTime, entity.flapTime);
|
|
state.deathTime = entity.dragonDeathTime > 0 ? (float)entity.dragonDeathTime + partialTicks : 0.0f;
|
|
state.hasRedOverlay = entity.hurtTime > 0;
|
|
EndCrystal nearestCrystal = entity.nearestCrystal;
|
|
if (nearestCrystal != null) {
|
|
Vec3 crystalPosition = nearestCrystal.getPosition(partialTicks).add(0.0, EndCrystalRenderer.getY((float)nearestCrystal.time + partialTicks), 0.0);
|
|
state.beamOffset = crystalPosition.subtract(entity.getPosition(partialTicks));
|
|
} else {
|
|
state.beamOffset = null;
|
|
}
|
|
DragonPhaseInstance phase = entity.getPhaseManager().getCurrentPhase();
|
|
state.isLandingOrTakingOff = phase == EnderDragonPhase.LANDING || phase == EnderDragonPhase.TAKEOFF;
|
|
state.isSitting = phase.isSitting();
|
|
BlockPos egg = entity.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(entity.getFightOrigin()));
|
|
state.distanceToEgg = egg.distToCenterSqr(entity.position());
|
|
state.partialTicks = entity.isDeadOrDying() ? 0.0f : partialTicks;
|
|
state.flightHistory.copyFrom(entity.flightHistory);
|
|
}
|
|
|
|
@Override
|
|
protected boolean affectedByCulling(EnderDragon entity) {
|
|
return false;
|
|
}
|
|
}
|
|
|