/* * 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; } }