2025-11-24 22:52:51 +03:00

916 lines
44 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.mojang.jtracy.TracyClient
* com.mojang.logging.LogUtils
* org.apache.commons.io.IOUtils
* org.joml.Matrix4f
* org.joml.Matrix4fStack
* org.joml.Matrix4fc
* org.joml.Quaternionf
* org.joml.Quaternionfc
* org.joml.Vector3f
* org.joml.Vector3fc
* org.joml.Vector4f
* org.jspecify.annotations.Nullable
* org.slf4j.Logger
*/
package net.minecraft.client.renderer;
import com.mojang.blaze3d.ProjectionType;
import com.mojang.blaze3d.buffers.GpuBufferSlice;
import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.Lighting;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.resource.CrossFrameResourcePool;
import com.mojang.blaze3d.shaders.ShaderSource;
import com.mojang.blaze3d.systems.GpuDevice;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.jtracy.TracyClient;
import com.mojang.logging.LogUtils;
import com.mojang.math.Axis;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.lang.runtime.SwitchBootstraps;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.List;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.SharedConstants;
import net.minecraft.client.Camera;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Options;
import net.minecraft.client.Screenshot;
import net.minecraft.client.entity.ClientAvatarState;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.debug.DebugScreenEntries;
import net.minecraft.client.gui.font.ActiveArea;
import net.minecraft.client.gui.font.EmptyArea;
import net.minecraft.client.gui.font.TextRenderable;
import net.minecraft.client.gui.render.GuiRenderer;
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.pip.GuiBannerResultRenderer;
import net.minecraft.client.gui.render.pip.GuiBookModelRenderer;
import net.minecraft.client.gui.render.pip.GuiEntityRenderer;
import net.minecraft.client.gui.render.pip.GuiProfilerChartRenderer;
import net.minecraft.client.gui.render.pip.GuiSignRenderer;
import net.minecraft.client.gui.render.pip.GuiSkinRenderer;
import net.minecraft.client.gui.render.state.ColoredRectangleRenderState;
import net.minecraft.client.gui.render.state.GuiRenderState;
import net.minecraft.client.gui.render.state.GuiTextRenderState;
import net.minecraft.client.gui.screens.debug.DebugOptionsScreen;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.CachedPerspectiveProjectionMatrixBuffer;
import net.minecraft.client.renderer.CubeMap;
import net.minecraft.client.renderer.GlobalSettingsUniform;
import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.LevelTargetBundle;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.PanoramaRenderer;
import net.minecraft.client.renderer.PanoramicScreenshotParameters;
import net.minecraft.client.renderer.PerspectiveProjectionMatrixBuffer;
import net.minecraft.client.renderer.PostChain;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.renderer.ScreenEffectRenderer;
import net.minecraft.client.renderer.SubmitNodeStorage;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.feature.FeatureRenderDispatcher;
import net.minecraft.client.renderer.fog.FogRenderer;
import net.minecraft.client.renderer.state.CameraRenderState;
import net.minecraft.client.renderer.state.LevelRenderState;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.resources.model.AtlasManager;
import net.minecraft.client.server.IntegratedServer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Style;
import net.minecraft.resources.Identifier;
import net.minecraft.server.packs.resources.ResourceProvider;
import net.minecraft.util.ARGB;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.util.Util;
import net.minecraft.util.profiling.Profiler;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.util.profiling.Zone;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.monster.Creeper;
import net.minecraft.world.entity.monster.EnderMan;
import net.minecraft.world.entity.monster.Spider;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraft.world.level.material.FogType;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.waypoints.TrackedWaypoint;
import org.apache.commons.io.IOUtils;
import org.joml.Matrix4f;
import org.joml.Matrix4fStack;
import org.joml.Matrix4fc;
import org.joml.Quaternionf;
import org.joml.Quaternionfc;
import org.joml.Vector3f;
import org.joml.Vector3fc;
import org.joml.Vector4f;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public class GameRenderer
implements AutoCloseable,
TrackedWaypoint.Projector {
private static final Identifier BLUR_POST_CHAIN_ID = Identifier.withDefaultNamespace("blur");
public static final int MAX_BLUR_RADIUS = 10;
private static final Logger LOGGER = LogUtils.getLogger();
public static final float PROJECTION_Z_NEAR = 0.05f;
public static final float PROJECTION_3D_HUD_Z_FAR = 100.0f;
private static final float PORTAL_SPINNING_SPEED = 20.0f;
private static final float NAUSEA_SPINNING_SPEED = 7.0f;
private final Minecraft minecraft;
private final RandomSource random = RandomSource.create();
private float renderDistance;
public final ItemInHandRenderer itemInHandRenderer;
private final ScreenEffectRenderer screenEffectRenderer;
private final RenderBuffers renderBuffers;
private float spinningEffectTime;
private float spinningEffectSpeed;
private float fovModifier;
private float oldFovModifier;
private float darkenWorldAmount;
private float darkenWorldAmountO;
private boolean renderBlockOutline = true;
private long lastScreenshotAttempt;
private boolean hasWorldScreenshot;
private long lastActiveTime = Util.getMillis();
private final LightTexture lightTexture;
private final OverlayTexture overlayTexture = new OverlayTexture();
private @Nullable PanoramicScreenshotParameters panoramicScreenshotParameters;
protected final CubeMap cubeMap = new CubeMap(Identifier.withDefaultNamespace("textures/gui/title/background/panorama"));
protected final PanoramaRenderer panorama = new PanoramaRenderer(this.cubeMap);
private final CrossFrameResourcePool resourcePool = new CrossFrameResourcePool(3);
private final FogRenderer fogRenderer = new FogRenderer();
private final GuiRenderer guiRenderer;
private final GuiRenderState guiRenderState;
private final LevelRenderState levelRenderState = new LevelRenderState();
private final SubmitNodeStorage submitNodeStorage;
private final FeatureRenderDispatcher featureRenderDispatcher;
private @Nullable Identifier postEffectId;
private boolean effectActive;
private final Camera mainCamera = new Camera();
private final Lighting lighting = new Lighting();
private final GlobalSettingsUniform globalSettingsUniform = new GlobalSettingsUniform();
private final PerspectiveProjectionMatrixBuffer levelProjectionMatrixBuffer = new PerspectiveProjectionMatrixBuffer("level");
private final CachedPerspectiveProjectionMatrixBuffer hud3dProjectionMatrixBuffer = new CachedPerspectiveProjectionMatrixBuffer("3d hud", 0.05f, 100.0f);
public GameRenderer(Minecraft minecraft, ItemInHandRenderer itemInHandRenderer, RenderBuffers renderBuffers, BlockRenderDispatcher blockRenderer) {
this.minecraft = minecraft;
this.itemInHandRenderer = itemInHandRenderer;
this.lightTexture = new LightTexture(this, minecraft);
this.renderBuffers = renderBuffers;
this.guiRenderState = new GuiRenderState();
MultiBufferSource.BufferSource bufferSource = renderBuffers.bufferSource();
AtlasManager atlasManager = minecraft.getAtlasManager();
this.submitNodeStorage = new SubmitNodeStorage();
this.featureRenderDispatcher = new FeatureRenderDispatcher(this.submitNodeStorage, blockRenderer, bufferSource, atlasManager, renderBuffers.outlineBufferSource(), renderBuffers.crumblingBufferSource(), minecraft.font);
this.guiRenderer = new GuiRenderer(this.guiRenderState, bufferSource, this.submitNodeStorage, this.featureRenderDispatcher, List.of(new GuiEntityRenderer(bufferSource, minecraft.getEntityRenderDispatcher()), new GuiSkinRenderer(bufferSource), new GuiBookModelRenderer(bufferSource), new GuiBannerResultRenderer(bufferSource, atlasManager), new GuiSignRenderer(bufferSource, atlasManager), new GuiProfilerChartRenderer(bufferSource)));
this.screenEffectRenderer = new ScreenEffectRenderer(minecraft, atlasManager, bufferSource);
}
@Override
public void close() {
this.globalSettingsUniform.close();
this.lightTexture.close();
this.overlayTexture.close();
this.resourcePool.close();
this.guiRenderer.close();
this.levelProjectionMatrixBuffer.close();
this.hud3dProjectionMatrixBuffer.close();
this.lighting.close();
this.cubeMap.close();
this.fogRenderer.close();
this.featureRenderDispatcher.close();
}
public SubmitNodeStorage getSubmitNodeStorage() {
return this.submitNodeStorage;
}
public FeatureRenderDispatcher getFeatureRenderDispatcher() {
return this.featureRenderDispatcher;
}
public LevelRenderState getLevelRenderState() {
return this.levelRenderState;
}
public void setRenderBlockOutline(boolean renderBlockOutline) {
this.renderBlockOutline = renderBlockOutline;
}
public void setPanoramicScreenshotParameters(@Nullable PanoramicScreenshotParameters panoramicScreenshotParameters) {
this.panoramicScreenshotParameters = panoramicScreenshotParameters;
}
public @Nullable PanoramicScreenshotParameters getPanoramicScreenshotParameters() {
return this.panoramicScreenshotParameters;
}
public boolean isPanoramicMode() {
return this.panoramicScreenshotParameters != null;
}
public void clearPostEffect() {
this.postEffectId = null;
this.effectActive = false;
}
public void togglePostEffect() {
this.effectActive = !this.effectActive;
}
public void checkEntityPostEffect(@Nullable Entity cameraEntity) {
Entity entity = cameraEntity;
int n = 0;
switch (SwitchBootstraps.typeSwitch("typeSwitch", new Object[]{Creeper.class, Spider.class, EnderMan.class}, (Object)entity, n)) {
case 0: {
Creeper ignored = (Creeper)entity;
this.setPostEffect(Identifier.withDefaultNamespace("creeper"));
break;
}
case 1: {
Spider ignored = (Spider)entity;
this.setPostEffect(Identifier.withDefaultNamespace("spider"));
break;
}
case 2: {
EnderMan ignored = (EnderMan)entity;
this.setPostEffect(Identifier.withDefaultNamespace("invert"));
break;
}
default: {
this.clearPostEffect();
}
}
}
private void setPostEffect(Identifier id) {
this.postEffectId = id;
this.effectActive = true;
}
public void processBlurEffect() {
PostChain postChain = this.minecraft.getShaderManager().getPostChain(BLUR_POST_CHAIN_ID, LevelTargetBundle.MAIN_TARGETS);
if (postChain != null) {
postChain.process(this.minecraft.getMainRenderTarget(), this.resourcePool);
}
}
public void preloadUiShader(ResourceProvider resourceProvider) {
GpuDevice device = RenderSystem.getDevice();
ShaderSource shaderSource = (id, type) -> {
String string;
block8: {
Identifier location = type.idConverter().idToFile(id);
BufferedReader reader = resourceProvider.getResourceOrThrow(location).openAsReader();
try {
string = IOUtils.toString((Reader)reader);
if (reader == null) break block8;
}
catch (Throwable throwable) {
try {
if (reader != null) {
try {
((Reader)reader).close();
}
catch (Throwable throwable2) {
throwable.addSuppressed(throwable2);
}
}
throw throwable;
}
catch (IOException exception) {
LOGGER.error("Coudln't preload {} shader {}: {}", new Object[]{type, id, exception});
return null;
}
}
((Reader)reader).close();
}
return string;
};
device.precompilePipeline(RenderPipelines.GUI, shaderSource);
device.precompilePipeline(RenderPipelines.GUI_TEXTURED, shaderSource);
if (TracyClient.isAvailable()) {
device.precompilePipeline(RenderPipelines.TRACY_BLIT, shaderSource);
}
}
public void tick() {
this.tickFov();
this.lightTexture.tick();
LocalPlayer player = this.minecraft.player;
if (this.minecraft.getCameraEntity() == null) {
this.minecraft.setCameraEntity(player);
}
this.mainCamera.tick();
this.itemInHandRenderer.tick();
float portalIntensity = player.portalEffectIntensity;
float nauseaIntensity = player.getEffectBlendFactor(MobEffects.NAUSEA, 1.0f);
if (portalIntensity > 0.0f || nauseaIntensity > 0.0f) {
this.spinningEffectSpeed = (portalIntensity * 20.0f + nauseaIntensity * 7.0f) / (portalIntensity + nauseaIntensity);
this.spinningEffectTime += this.spinningEffectSpeed;
} else {
this.spinningEffectSpeed = 0.0f;
}
if (!this.minecraft.level.tickRateManager().runsNormally()) {
return;
}
this.darkenWorldAmountO = this.darkenWorldAmount;
if (this.minecraft.gui.getBossOverlay().shouldDarkenScreen()) {
this.darkenWorldAmount += 0.05f;
if (this.darkenWorldAmount > 1.0f) {
this.darkenWorldAmount = 1.0f;
}
} else if (this.darkenWorldAmount > 0.0f) {
this.darkenWorldAmount -= 0.0125f;
}
this.screenEffectRenderer.tick();
ProfilerFiller profiler = Profiler.get();
profiler.push("levelRenderer");
this.minecraft.levelRenderer.tick(this.mainCamera);
profiler.pop();
}
public @Nullable Identifier currentPostEffect() {
return this.postEffectId;
}
public void resize(int width, int height) {
this.resourcePool.clear();
this.minecraft.levelRenderer.resize(width, height);
}
public void pick(float a) {
Entity entity;
HitResult hitResult;
Entity cameraEntity = this.minecraft.getCameraEntity();
if (cameraEntity == null) {
return;
}
if (this.minecraft.level == null || this.minecraft.player == null) {
return;
}
Profiler.get().push("pick");
double blockInteractionRange = this.minecraft.player.blockInteractionRange();
double entityInteractionRange = this.minecraft.player.entityInteractionRange();
this.minecraft.hitResult = hitResult = this.pick(cameraEntity, blockInteractionRange, entityInteractionRange, a);
if (hitResult instanceof EntityHitResult) {
EntityHitResult entityHitResult = (EntityHitResult)hitResult;
entity = entityHitResult.getEntity();
} else {
entity = null;
}
this.minecraft.crosshairPickEntity = entity;
Profiler.get().pop();
}
private HitResult pick(Entity cameraEntity, double blockInteractionRange, double entityInteractionRange, float partialTicks) {
double maxDistance = Math.max(blockInteractionRange, entityInteractionRange);
double maxDistanceSq = Mth.square(maxDistance);
Vec3 from = cameraEntity.getEyePosition(partialTicks);
HitResult blockHitResult = cameraEntity.pick(maxDistance, partialTicks, false);
double blockDistanceSq = blockHitResult.getLocation().distanceToSqr(from);
if (blockHitResult.getType() != HitResult.Type.MISS) {
maxDistanceSq = blockDistanceSq;
maxDistance = Math.sqrt(maxDistanceSq);
}
Vec3 direction = cameraEntity.getViewVector(partialTicks);
Vec3 to = from.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance);
float overlap = 1.0f;
AABB box = cameraEntity.getBoundingBox().expandTowards(direction.scale(maxDistance)).inflate(1.0, 1.0, 1.0);
EntityHitResult entityHitResult = ProjectileUtil.getEntityHitResult(cameraEntity, from, to, box, EntitySelector.CAN_BE_PICKED, maxDistanceSq);
if (entityHitResult != null && entityHitResult.getLocation().distanceToSqr(from) < blockDistanceSq) {
return GameRenderer.filterHitResult(entityHitResult, from, entityInteractionRange);
}
return GameRenderer.filterHitResult(blockHitResult, from, blockInteractionRange);
}
private static HitResult filterHitResult(HitResult hitResult, Vec3 from, double maxRange) {
Vec3 hitLocation = hitResult.getLocation();
if (!hitLocation.closerThan(from, maxRange)) {
Vec3 location = hitResult.getLocation();
Direction direction = Direction.getApproximateNearest(location.x - from.x, location.y - from.y, location.z - from.z);
return BlockHitResult.miss(location, direction, BlockPos.containing(location));
}
return hitResult;
}
private void tickFov() {
float targetFovModifier;
Entity entity = this.minecraft.getCameraEntity();
if (entity instanceof AbstractClientPlayer) {
AbstractClientPlayer player = (AbstractClientPlayer)entity;
Options options = this.minecraft.options;
boolean firstPerson = options.getCameraType().isFirstPerson();
float effectScale = options.fovEffectScale().get().floatValue();
targetFovModifier = player.getFieldOfViewModifier(firstPerson, effectScale);
} else {
targetFovModifier = 1.0f;
}
this.oldFovModifier = this.fovModifier;
this.fovModifier += (targetFovModifier - this.fovModifier) * 0.5f;
this.fovModifier = Mth.clamp(this.fovModifier, 0.1f, 1.5f);
}
private float getFov(Camera camera, float partialTicks, boolean applyEffects) {
FogType state;
LivingEntity cameraEntity;
Entity entity;
if (this.isPanoramicMode()) {
return 90.0f;
}
float fov = 70.0f;
if (applyEffects) {
fov = this.minecraft.options.fov().get().intValue();
fov *= Mth.lerp(partialTicks, this.oldFovModifier, this.fovModifier);
}
if ((entity = camera.entity()) instanceof LivingEntity && (cameraEntity = (LivingEntity)entity).isDeadOrDying()) {
float duration = Math.min((float)cameraEntity.deathTime + partialTicks, 20.0f);
fov /= (1.0f - 500.0f / (duration + 500.0f)) * 2.0f + 1.0f;
}
if ((state = camera.getFluidInCamera()) == FogType.LAVA || state == FogType.WATER) {
float effectScale = this.minecraft.options.fovEffectScale().get().floatValue();
fov *= Mth.lerp(effectScale, 1.0f, 0.85714287f);
}
return fov;
}
private void bobHurt(PoseStack poseStack, float a) {
Entity entity = this.minecraft.getCameraEntity();
if (entity instanceof LivingEntity) {
LivingEntity camera = (LivingEntity)entity;
float hurt = (float)camera.hurtTime - a;
if (camera.isDeadOrDying()) {
float duration = Math.min((float)camera.deathTime + a, 20.0f);
poseStack.mulPose((Quaternionfc)Axis.ZP.rotationDegrees(40.0f - 8000.0f / (duration + 200.0f)));
}
if (hurt < 0.0f) {
return;
}
hurt /= (float)camera.hurtDuration;
hurt = Mth.sin(hurt * hurt * hurt * hurt * (float)Math.PI);
float rr = camera.getHurtDir();
poseStack.mulPose((Quaternionfc)Axis.YP.rotationDegrees(-rr));
float tiltAmount = (float)((double)(-hurt) * 14.0 * this.minecraft.options.damageTiltStrength().get());
poseStack.mulPose((Quaternionfc)Axis.ZP.rotationDegrees(tiltAmount));
poseStack.mulPose((Quaternionfc)Axis.YP.rotationDegrees(rr));
}
}
private void bobView(PoseStack poseStack, float a) {
Entity entity = this.minecraft.getCameraEntity();
if (!(entity instanceof AbstractClientPlayer)) {
return;
}
AbstractClientPlayer player = (AbstractClientPlayer)entity;
ClientAvatarState avatarState = player.avatarState();
float b = avatarState.getBackwardsInterpolatedWalkDistance(a);
float bob = avatarState.getInterpolatedBob(a);
poseStack.translate(Mth.sin(b * (float)Math.PI) * bob * 0.5f, -Math.abs(Mth.cos(b * (float)Math.PI) * bob), 0.0f);
poseStack.mulPose((Quaternionfc)Axis.ZP.rotationDegrees(Mth.sin(b * (float)Math.PI) * bob * 3.0f));
poseStack.mulPose((Quaternionfc)Axis.XP.rotationDegrees(Math.abs(Mth.cos(b * (float)Math.PI - 0.2f) * bob) * 5.0f));
}
private void renderItemInHand(float deltaPartialTick, boolean isSleeping, Matrix4f modelViewMatrix) {
if (this.isPanoramicMode()) {
return;
}
this.featureRenderDispatcher.renderAllFeatures();
this.renderBuffers.bufferSource().endBatch();
PoseStack poseStack = new PoseStack();
poseStack.pushPose();
poseStack.mulPose((Matrix4fc)modelViewMatrix.invert(new Matrix4f()));
Matrix4fStack modelViewStack = RenderSystem.getModelViewStack();
modelViewStack.pushMatrix().mul((Matrix4fc)modelViewMatrix);
this.bobHurt(poseStack, deltaPartialTick);
if (this.minecraft.options.bobView().get().booleanValue()) {
this.bobView(poseStack, deltaPartialTick);
}
if (this.minecraft.options.getCameraType().isFirstPerson() && !isSleeping && !this.minecraft.options.hideGui && this.minecraft.gameMode.getPlayerMode() != GameType.SPECTATOR) {
this.itemInHandRenderer.renderHandsWithItems(deltaPartialTick, poseStack, this.minecraft.gameRenderer.getSubmitNodeStorage(), this.minecraft.player, this.minecraft.getEntityRenderDispatcher().getPackedLightCoords(this.minecraft.player, deltaPartialTick));
}
modelViewStack.popMatrix();
poseStack.popPose();
}
public Matrix4f getProjectionMatrix(float fov) {
Matrix4f projection = new Matrix4f();
return projection.perspective(fov * ((float)Math.PI / 180), (float)this.minecraft.getWindow().getWidth() / (float)this.minecraft.getWindow().getHeight(), 0.05f, this.getDepthFar());
}
public float getDepthFar() {
return Math.max(this.renderDistance * 4.0f, (float)(this.minecraft.options.cloudRange().get() * 16));
}
public static float getNightVisionScale(LivingEntity camera, float a) {
MobEffectInstance nightVision = camera.getEffect(MobEffects.NIGHT_VISION);
if (!nightVision.endsWithin(200)) {
return 1.0f;
}
return 0.7f + Mth.sin(((float)nightVision.getDuration() - a) * (float)Math.PI * 0.2f) * 0.3f;
}
public void render(DeltaTracker deltaTracker, boolean renderLevel) {
if (this.minecraft.isWindowActive() || !this.minecraft.options.pauseOnLostFocus || this.minecraft.options.touchscreen().get().booleanValue() && this.minecraft.mouseHandler.isRightPressed()) {
this.lastActiveTime = Util.getMillis();
} else if (Util.getMillis() - this.lastActiveTime > 500L) {
this.minecraft.pauseGame(false);
}
if (this.minecraft.noRender) {
return;
}
ProfilerFiller profiler = Profiler.get();
profiler.push("camera");
this.updateCamera(deltaTracker);
profiler.pop();
this.globalSettingsUniform.update(this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight(), this.minecraft.options.glintStrength().get(), this.minecraft.level == null ? 0L : this.minecraft.level.getGameTime(), deltaTracker, this.minecraft.options.getMenuBackgroundBlurriness(), this.mainCamera);
boolean resourcesLoaded = this.minecraft.isGameLoadFinished();
int xMouse = (int)this.minecraft.mouseHandler.getScaledXPos(this.minecraft.getWindow());
int yMouse = (int)this.minecraft.mouseHandler.getScaledYPos(this.minecraft.getWindow());
if (resourcesLoaded && renderLevel && this.minecraft.level != null) {
PostChain postChain;
profiler.push("world");
this.renderLevel(deltaTracker);
this.tryTakeScreenshotIfNeeded();
this.minecraft.levelRenderer.doEntityOutline();
if (this.postEffectId != null && this.effectActive && (postChain = this.minecraft.getShaderManager().getPostChain(this.postEffectId, LevelTargetBundle.MAIN_TARGETS)) != null) {
postChain.process(this.minecraft.getMainRenderTarget(), this.resourcePool);
}
profiler.pop();
}
this.fogRenderer.endFrame();
RenderTarget mainRenderTarget = this.minecraft.getMainRenderTarget();
RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(mainRenderTarget.getDepthTexture(), 1.0);
this.minecraft.gameRenderer.getLighting().setupFor(Lighting.Entry.ITEMS_3D);
this.guiRenderState.reset();
profiler.push("guiExtraction");
GuiGraphics graphics = new GuiGraphics(this.minecraft, this.guiRenderState, xMouse, yMouse);
if (resourcesLoaded && renderLevel && this.minecraft.level != null) {
this.minecraft.gui.render(graphics, deltaTracker);
}
if (this.minecraft.getOverlay() != null) {
try {
this.minecraft.getOverlay().render(graphics, xMouse, yMouse, deltaTracker.getGameTimeDeltaTicks());
}
catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "Rendering overlay");
CrashReportCategory category = report.addCategory("Overlay render details");
category.setDetail("Overlay name", () -> this.minecraft.getOverlay().getClass().getCanonicalName());
throw new ReportedException(report);
}
}
if (resourcesLoaded && this.minecraft.screen != null) {
try {
this.minecraft.screen.renderWithTooltipAndSubtitles(graphics, xMouse, yMouse, deltaTracker.getGameTimeDeltaTicks());
}
catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "Rendering screen");
CrashReportCategory category = report.addCategory("Screen render details");
category.setDetail("Screen name", () -> this.minecraft.screen.getClass().getCanonicalName());
this.minecraft.mouseHandler.fillMousePositionDetails(category, this.minecraft.getWindow());
throw new ReportedException(report);
}
if (SharedConstants.DEBUG_CURSOR_POS) {
this.minecraft.mouseHandler.drawDebugMouseInfo(this.minecraft.font, graphics);
}
try {
if (this.minecraft.screen != null) {
this.minecraft.screen.handleDelayedNarration();
}
}
catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "Narrating screen");
CrashReportCategory category = report.addCategory("Screen details");
category.setDetail("Screen name", () -> this.minecraft.screen.getClass().getCanonicalName());
throw new ReportedException(report);
}
}
if (resourcesLoaded && renderLevel && this.minecraft.level != null) {
this.minecraft.gui.renderSavingIndicator(graphics, deltaTracker);
}
if (resourcesLoaded) {
try (Zone ignored = profiler.zone("toasts");){
this.minecraft.getToastManager().render(graphics);
}
}
if (!(this.minecraft.screen instanceof DebugOptionsScreen)) {
this.minecraft.gui.renderDebugOverlay(graphics);
}
this.minecraft.gui.renderDeferredSubtitles();
if (SharedConstants.DEBUG_ACTIVE_TEXT_AREAS) {
this.renderActiveTextDebug();
}
profiler.popPush("guiRendering");
this.guiRenderer.render(this.fogRenderer.getBuffer(FogRenderer.FogMode.NONE));
this.guiRenderer.incrementFrameNumber();
profiler.pop();
graphics.applyCursor(this.minecraft.getWindow());
this.submitNodeStorage.endFrame();
this.featureRenderDispatcher.endFrame();
this.resourcePool.endFrame();
}
private void renderActiveTextDebug() {
this.guiRenderState.nextStratum();
this.guiRenderState.forEachText(text -> text.ensurePrepared().visit(new Font.GlyphVisitor(){
private int index;
final /* synthetic */ GuiTextRenderState val$text;
{
this.val$text = guiTextRenderState;
}
@Override
public void acceptGlyph(TextRenderable.Styled glyph) {
this.renderDebugMarkers(glyph, false);
}
@Override
public void acceptEmptyArea(EmptyArea empty) {
this.renderDebugMarkers(empty, true);
}
private void renderDebugMarkers(ActiveArea glyph, boolean isEmpty) {
int intensity = (isEmpty ? 128 : 255) - (this.index++ & 1) * 64;
Style style = glyph.style();
int red = style.getClickEvent() != null ? intensity : 0;
int green = style.getHoverEvent() != null ? intensity : 0;
int blue = red == 0 || green == 0 ? intensity : 0;
int color = ARGB.color(128, red, green, blue);
GameRenderer.this.guiRenderState.submitGuiElement(new ColoredRectangleRenderState(RenderPipelines.GUI, TextureSetup.noTexture(), this.val$text.pose, (int)glyph.activeLeft(), (int)glyph.activeTop(), (int)glyph.activeRight(), (int)glyph.activeBottom(), color, color, this.val$text.scissor));
}
}));
}
private void tryTakeScreenshotIfNeeded() {
if (this.hasWorldScreenshot || !this.minecraft.isLocalServer()) {
return;
}
long time = Util.getMillis();
if (time - this.lastScreenshotAttempt < 1000L) {
return;
}
this.lastScreenshotAttempt = time;
IntegratedServer server = this.minecraft.getSingleplayerServer();
if (server == null || server.isStopped()) {
return;
}
server.getWorldScreenshotFile().ifPresent(path -> {
if (Files.isRegularFile(path, new LinkOption[0])) {
this.hasWorldScreenshot = true;
} else {
this.takeAutoScreenshot((Path)path);
}
});
}
private void takeAutoScreenshot(Path screenshotFile) {
if (this.minecraft.levelRenderer.countRenderedSections() > 10 && this.minecraft.levelRenderer.hasRenderedAllSections()) {
Screenshot.takeScreenshot(this.minecraft.getMainRenderTarget(), screenshot -> Util.ioPool().execute(() -> {
int width = screenshot.getWidth();
int height = screenshot.getHeight();
int x = 0;
int y = 0;
if (width > height) {
x = (width - height) / 2;
width = height;
} else {
y = (height - width) / 2;
height = width;
}
try (NativeImage scaled = new NativeImage(64, 64, false);){
screenshot.resizeSubRectTo(x, y, width, height, scaled);
scaled.writeToFile(screenshotFile);
}
catch (IOException e) {
LOGGER.warn("Couldn't save auto screenshot", (Throwable)e);
}
finally {
screenshot.close();
}
}));
}
}
private boolean shouldRenderBlockOutline() {
boolean renderOutline;
if (!this.renderBlockOutline) {
return false;
}
Entity cameraEntity = this.minecraft.getCameraEntity();
boolean bl = renderOutline = cameraEntity instanceof Player && !this.minecraft.options.hideGui;
if (renderOutline && !((Player)cameraEntity).getAbilities().mayBuild) {
ItemStack itemStack = ((LivingEntity)cameraEntity).getMainHandItem();
HitResult hitResult = this.minecraft.hitResult;
if (hitResult != null && hitResult.getType() == HitResult.Type.BLOCK) {
BlockPos pos = ((BlockHitResult)hitResult).getBlockPos();
BlockState blockState = this.minecraft.level.getBlockState(pos);
if (this.minecraft.gameMode.getPlayerMode() == GameType.SPECTATOR) {
renderOutline = blockState.getMenuProvider(this.minecraft.level, pos) != null;
} else {
BlockInWorld blockInWorld = new BlockInWorld(this.minecraft.level, pos, false);
HolderLookup.RegistryLookup blockRegistry = this.minecraft.level.registryAccess().lookupOrThrow(Registries.BLOCK);
renderOutline = !itemStack.isEmpty() && (itemStack.canBreakBlockInAdventureMode(blockInWorld) || itemStack.canPlaceOnBlockInAdventureMode(blockInWorld));
}
}
}
return renderOutline;
}
public void updateCamera(DeltaTracker deltaTracker) {
float deltaPartialTick = deltaTracker.getGameTimeDeltaPartialTick(true);
LocalPlayer player = this.minecraft.player;
if (player == null || this.minecraft.level == null) {
return;
}
if (this.minecraft.getCameraEntity() == null) {
this.minecraft.setCameraEntity(player);
}
LocalPlayer cameraEntity = this.minecraft.getCameraEntity() == null ? player : this.minecraft.getCameraEntity();
float cameraDeltaPartialTicks = this.minecraft.level.tickRateManager().isEntityFrozen(cameraEntity) ? 1.0f : deltaPartialTick;
this.mainCamera.setup(this.minecraft.level, cameraEntity, !this.minecraft.options.getCameraType().isFirstPerson(), this.minecraft.options.getCameraType().isMirrored(), cameraDeltaPartialTicks);
}
public void renderLevel(DeltaTracker deltaTracker) {
float deltaPartialTick = deltaTracker.getGameTimeDeltaPartialTick(true);
LocalPlayer player = this.minecraft.player;
this.lightTexture.updateLightTexture(1.0f);
this.pick(deltaPartialTick);
ProfilerFiller profiler = Profiler.get();
boolean renderOutline = this.shouldRenderBlockOutline();
this.extractCamera(deltaPartialTick);
this.renderDistance = this.minecraft.options.getEffectiveRenderDistance() * 16;
profiler.push("matrices");
float fovWithEffects = this.getFov(this.mainCamera, deltaPartialTick, true);
Matrix4f projectionMatrix = this.getProjectionMatrix(fovWithEffects);
PoseStack bobStack = new PoseStack();
this.bobHurt(bobStack, this.mainCamera.getPartialTickTime());
if (this.minecraft.options.bobView().get().booleanValue()) {
this.bobView(bobStack, this.mainCamera.getPartialTickTime());
}
projectionMatrix.mul((Matrix4fc)bobStack.last().pose());
float screenEffectScale = this.minecraft.options.screenEffectScale().get().floatValue();
float portalIntensity = Mth.lerp(deltaPartialTick, player.oPortalEffectIntensity, player.portalEffectIntensity);
float nauseaIntensity = player.getEffectBlendFactor(MobEffects.NAUSEA, deltaPartialTick);
float spinningEffectIntensity = Math.max(portalIntensity, nauseaIntensity) * (screenEffectScale * screenEffectScale);
if (spinningEffectIntensity > 0.0f) {
float skew = 5.0f / (spinningEffectIntensity * spinningEffectIntensity + 5.0f) - spinningEffectIntensity * 0.04f;
skew *= skew;
Vector3f axis = new Vector3f(0.0f, Mth.SQRT_OF_TWO / 2.0f, Mth.SQRT_OF_TWO / 2.0f);
float angle = (this.spinningEffectTime + deltaPartialTick * this.spinningEffectSpeed) * ((float)Math.PI / 180);
projectionMatrix.rotate(angle, (Vector3fc)axis);
projectionMatrix.scale(1.0f / skew, 1.0f, 1.0f);
projectionMatrix.rotate(-angle, (Vector3fc)axis);
}
RenderSystem.setProjectionMatrix(this.levelProjectionMatrixBuffer.getBuffer(projectionMatrix), ProjectionType.PERSPECTIVE);
Quaternionf inverseRotation = this.mainCamera.rotation().conjugate(new Quaternionf());
Matrix4f modelViewMatrix = new Matrix4f().rotation((Quaternionfc)inverseRotation);
profiler.popPush("fog");
Vector4f fogColor = this.fogRenderer.setupFog(this.mainCamera, this.minecraft.options.getEffectiveRenderDistance(), deltaTracker, this.getDarkenWorldAmount(deltaPartialTick), this.minecraft.level);
GpuBufferSlice terrainFog = this.fogRenderer.getBuffer(FogRenderer.FogMode.WORLD);
profiler.popPush("level");
boolean shouldCreateBossFog = this.minecraft.gui.getBossOverlay().shouldCreateWorldFog();
this.minecraft.levelRenderer.renderLevel(this.resourcePool, deltaTracker, renderOutline, this.mainCamera, modelViewMatrix, projectionMatrix, this.getProjectionMatrixForCulling(fovWithEffects), terrainFog, fogColor, !shouldCreateBossFog);
profiler.popPush("hand");
boolean isSleeping = this.minecraft.getCameraEntity() instanceof LivingEntity && ((LivingEntity)this.minecraft.getCameraEntity()).isSleeping();
RenderSystem.setProjectionMatrix(this.hud3dProjectionMatrixBuffer.getBuffer(this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight(), this.getFov(this.mainCamera, deltaPartialTick, false)), ProjectionType.PERSPECTIVE);
RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(this.minecraft.getMainRenderTarget().getDepthTexture(), 1.0);
this.renderItemInHand(deltaPartialTick, isSleeping, modelViewMatrix);
profiler.popPush("screenEffects");
MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource();
this.screenEffectRenderer.renderScreenEffect(isSleeping, deltaPartialTick, this.submitNodeStorage);
this.featureRenderDispatcher.renderAllFeatures();
bufferSource.endBatch();
profiler.pop();
RenderSystem.setShaderFog(this.fogRenderer.getBuffer(FogRenderer.FogMode.NONE));
if (this.minecraft.debugEntries.isCurrentlyEnabled(DebugScreenEntries.THREE_DIMENSIONAL_CROSSHAIR) && this.minecraft.options.getCameraType().isFirstPerson() && !this.minecraft.options.hideGui) {
this.minecraft.getDebugOverlay().render3dCrosshair(this.mainCamera);
}
}
private void extractCamera(float partialTicks) {
CameraRenderState cameraState = this.levelRenderState.cameraRenderState;
cameraState.initialized = this.mainCamera.isInitialized();
cameraState.pos = this.mainCamera.position();
cameraState.blockPos = this.mainCamera.blockPosition();
cameraState.entityPos = this.mainCamera.entity().getPosition(partialTicks);
cameraState.orientation = new Quaternionf((Quaternionfc)this.mainCamera.rotation());
}
private Matrix4f getProjectionMatrixForCulling(float fovWithEffects) {
float fovForCulling = Math.max(fovWithEffects, (float)this.minecraft.options.fov().get().intValue());
return this.getProjectionMatrix(fovForCulling);
}
public void resetData() {
this.screenEffectRenderer.resetItemActivation();
this.minecraft.getMapTextureManager().resetData();
this.mainCamera.reset();
this.hasWorldScreenshot = false;
}
public void displayItemActivation(ItemStack itemStack) {
this.screenEffectRenderer.displayItemActivation(itemStack, this.random);
}
public Minecraft getMinecraft() {
return this.minecraft;
}
public float getDarkenWorldAmount(float a) {
return Mth.lerp(a, this.darkenWorldAmountO, this.darkenWorldAmount);
}
public float getRenderDistance() {
return this.renderDistance;
}
public Camera getMainCamera() {
return this.mainCamera;
}
public LightTexture lightTexture() {
return this.lightTexture;
}
public OverlayTexture overlayTexture() {
return this.overlayTexture;
}
@Override
public Vec3 projectPointToScreen(Vec3 point) {
Matrix4f projectionMatrix = this.getProjectionMatrix(this.getFov(this.mainCamera, 0.0f, true));
Quaternionf inverseRotation = this.mainCamera.rotation().conjugate(new Quaternionf());
Matrix4f modelViewMatrix = new Matrix4f().rotation((Quaternionfc)inverseRotation);
Matrix4f mvp = projectionMatrix.mul((Matrix4fc)modelViewMatrix);
Vec3 camPos = this.mainCamera.position();
Vec3 offset = point.subtract(camPos);
Vector3f vector3f = mvp.transformProject(offset.toVector3f());
return new Vec3((Vector3fc)vector3f);
}
@Override
public double projectHorizonToScreen() {
float xRot = this.mainCamera.xRot();
if (xRot <= -90.0f) {
return Double.NEGATIVE_INFINITY;
}
if (xRot >= 90.0f) {
return Double.POSITIVE_INFINITY;
}
float fov = this.getFov(this.mainCamera, 0.0f, true);
return Math.tan(xRot * ((float)Math.PI / 180)) / Math.tan(fov / 2.0f * ((float)Math.PI / 180));
}
public GlobalSettingsUniform getGlobalSettingsUniform() {
return this.globalSettingsUniform;
}
public Lighting getLighting() {
return this.lighting;
}
public void setLevel(@Nullable ClientLevel level) {
if (level != null) {
this.lighting.updateLevel(level.dimensionType().cardinalLightType());
}
}
public PanoramaRenderer getPanorama() {
return this.panorama;
}
}