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.ShaderType; 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.IOException; import java.io.Reader; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.util.List; import java.util.function.BiFunction; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.CrashReport; import net.minecraft.CrashReportCategory; import net.minecraft.CrashReportDetail; import net.minecraft.ReportedException; import net.minecraft.Util; 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.gui.GuiGraphics; import net.minecraft.client.gui.render.GuiRenderer; 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.GuiRenderState; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.fog.FogRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.server.IntegratedServer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceProvider; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; 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.Block; 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.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.joml.Matrix4fStack; import org.joml.Quaternionf; import org.joml.Vector3f; import org.joml.Vector4f; import org.slf4j.Logger; @Environment(EnvType.CLIENT) public class GameRenderer implements TrackedWaypoint.Projector, AutoCloseable { private static final ResourceLocation BLUR_POST_CHAIN_ID = ResourceLocation.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 boolean panoramicMode; protected final CubeMap cubeMap = new CubeMap(ResourceLocation.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; @Nullable private ResourceLocation 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) { this.minecraft = minecraft; this.itemInHandRenderer = itemInHandRenderer; this.lightTexture = new LightTexture(this, minecraft); this.renderBuffers = renderBuffers; this.guiRenderState = new GuiRenderState(); MultiBufferSource.BufferSource bufferSource = renderBuffers.bufferSource(); this.guiRenderer = new GuiRenderer( this.guiRenderState, bufferSource, List.of( new GuiEntityRenderer(bufferSource, minecraft.getEntityRenderDispatcher()), new GuiSkinRenderer(bufferSource), new GuiBookModelRenderer(bufferSource), new GuiBannerResultRenderer(bufferSource), new GuiSignRenderer(bufferSource), new GuiProfilerChartRenderer(bufferSource) ) ); this.screenEffectRenderer = new ScreenEffectRenderer(minecraft, bufferSource); } 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(); } public void setRenderBlockOutline(boolean renderBlockOutline) { this.renderBlockOutline = renderBlockOutline; } public void setPanoramicMode(boolean panoramicMode) { this.panoramicMode = panoramicMode; } public boolean isPanoramicMode() { return this.panoramicMode; } public void clearPostEffect() { this.postEffectId = null; } public void togglePostEffect() { this.effectActive = !this.effectActive; } /** * What shader to use when spectating this entity */ public void checkEntityPostEffect(@Nullable Entity entity) { this.postEffectId = null; if (entity instanceof Creeper) { this.setPostEffect(ResourceLocation.withDefaultNamespace("creeper")); } else if (entity instanceof Spider) { this.setPostEffect(ResourceLocation.withDefaultNamespace("spider")); } else if (entity instanceof EnderMan) { this.setPostEffect(ResourceLocation.withDefaultNamespace("invert")); } } private void setPostEffect(ResourceLocation postEffectId) { this.postEffectId = postEffectId; 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 gpuDevice = RenderSystem.getDevice(); BiFunction biFunction = (resourceLocation, shaderType) -> { ResourceLocation resourceLocation2 = shaderType.idConverter().idToFile(resourceLocation); try { Reader reader = resourceProvider.getResourceOrThrow(resourceLocation2).openAsReader(); String var5; try { var5 = IOUtils.toString(reader); } catch (Throwable var8) { if (reader != null) { try { reader.close(); } catch (Throwable var7) { var8.addSuppressed(var7); } } throw var8; } if (reader != null) { reader.close(); } return var5; } catch (IOException var9) { LOGGER.error("Coudln't preload {} shader {}: {}", shaderType, resourceLocation, var9); return null; } }; gpuDevice.precompilePipeline(RenderPipelines.GUI, biFunction); gpuDevice.precompilePipeline(RenderPipelines.GUI_TEXTURED, biFunction); if (TracyClient.isAvailable()) { gpuDevice.precompilePipeline(RenderPipelines.TRACY_BLIT, biFunction); } } /** * Updates the entity renderer */ public void tick() { this.tickFov(); this.lightTexture.tick(); LocalPlayer localPlayer = this.minecraft.player; if (this.minecraft.getCameraEntity() == null) { this.minecraft.setCameraEntity(localPlayer); } this.mainCamera.tick(); this.itemInHandRenderer.tick(); float f = localPlayer.portalEffectIntensity; float g = localPlayer.getEffectBlendFactor(MobEffects.NAUSEA, 1.0F); if (!(f > 0.0F) && !(g > 0.0F)) { this.spinningEffectSpeed = 0.0F; } else { this.spinningEffectSpeed = (f * 20.0F + g * 7.0F) / (f + g); this.spinningEffectTime = this.spinningEffectTime + this.spinningEffectSpeed; } if (this.minecraft.level.tickRateManager().runsNormally()) { this.minecraft.levelRenderer.tickParticles(this.mainCamera); 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(); } } @Nullable public ResourceLocation currentPostEffect() { return this.postEffectId; } public void resize(int width, int height) { this.resourcePool.clear(); this.minecraft.levelRenderer.resize(width, height); } /** * Gets the block or object that is being moused over. */ public void pick(float partialTicks) { Entity entity = this.minecraft.getCameraEntity(); if (entity != null) { if (this.minecraft.level != null && this.minecraft.player != null) { Profiler.get().push("pick"); double d = this.minecraft.player.blockInteractionRange(); double e = this.minecraft.player.entityInteractionRange(); HitResult hitResult = this.pick(entity, d, e, partialTicks); this.minecraft.hitResult = hitResult; this.minecraft.crosshairPickEntity = hitResult instanceof EntityHitResult entityHitResult ? entityHitResult.getEntity() : null; Profiler.get().pop(); } } } private HitResult pick(Entity entity, double blockInteractionRange, double entityInteractionRange, float partialTick) { double d = Math.max(blockInteractionRange, entityInteractionRange); double e = Mth.square(d); Vec3 vec3 = entity.getEyePosition(partialTick); HitResult hitResult = entity.pick(d, partialTick, false); double f = hitResult.getLocation().distanceToSqr(vec3); if (hitResult.getType() != HitResult.Type.MISS) { e = f; d = Math.sqrt(f); } Vec3 vec32 = entity.getViewVector(partialTick); Vec3 vec33 = vec3.add(vec32.x * d, vec32.y * d, vec32.z * d); float g = 1.0F; AABB aABB = entity.getBoundingBox().expandTowards(vec32.scale(d)).inflate(1.0, 1.0, 1.0); EntityHitResult entityHitResult = ProjectileUtil.getEntityHitResult(entity, vec3, vec33, aABB, EntitySelector.CAN_BE_PICKED, e); return entityHitResult != null && entityHitResult.getLocation().distanceToSqr(vec3) < f ? filterHitResult(entityHitResult, vec3, entityInteractionRange) : filterHitResult(hitResult, vec3, blockInteractionRange); } private static HitResult filterHitResult(HitResult hitResult, Vec3 pos, double blockInteractionRange) { Vec3 vec3 = hitResult.getLocation(); if (!vec3.closerThan(pos, blockInteractionRange)) { Vec3 vec32 = hitResult.getLocation(); Direction direction = Direction.getApproximateNearest(vec32.x - pos.x, vec32.y - pos.y, vec32.z - pos.z); return BlockHitResult.miss(vec32, direction, BlockPos.containing(vec32)); } else { return hitResult; } } /** * Update FOV modifier hand */ private void tickFov() { float g; if (this.minecraft.getCameraEntity() instanceof AbstractClientPlayer abstractClientPlayer) { Options options = this.minecraft.options; boolean bl = options.getCameraType().isFirstPerson(); float f = options.fovEffectScale().get().floatValue(); g = abstractClientPlayer.getFieldOfViewModifier(bl, f); } else { g = 1.0F; } this.oldFovModifier = this.fovModifier; this.fovModifier = this.fovModifier + (g - this.fovModifier) * 0.5F; this.fovModifier = Mth.clamp(this.fovModifier, 0.1F, 1.5F); } private float getFov(Camera camera, float partialTick, boolean useFovSetting) { if (this.panoramicMode) { return 90.0F; } else { float f = 70.0F; if (useFovSetting) { f = this.minecraft.options.fov().get().intValue(); f *= Mth.lerp(partialTick, this.oldFovModifier, this.fovModifier); } if (camera.getEntity() instanceof LivingEntity livingEntity && livingEntity.isDeadOrDying()) { float g = Math.min(livingEntity.deathTime + partialTick, 20.0F); f /= (1.0F - 500.0F / (g + 500.0F)) * 2.0F + 1.0F; } FogType fogType = camera.getFluidInCamera(); if (fogType == FogType.LAVA || fogType == FogType.WATER) { float g = this.minecraft.options.fovEffectScale().get().floatValue(); f *= Mth.lerp(g, 1.0F, 0.85714287F); } return f; } } private void bobHurt(PoseStack poseStack, float partialTicks) { if (this.minecraft.getCameraEntity() instanceof LivingEntity livingEntity) { float f = livingEntity.hurtTime - partialTicks; if (livingEntity.isDeadOrDying()) { float g = Math.min(livingEntity.deathTime + partialTicks, 20.0F); poseStack.mulPose(Axis.ZP.rotationDegrees(40.0F - 8000.0F / (g + 200.0F))); } if (f < 0.0F) { return; } f /= livingEntity.hurtDuration; f = Mth.sin(f * f * f * f * (float) Math.PI); float g = livingEntity.getHurtDir(); poseStack.mulPose(Axis.YP.rotationDegrees(-g)); float h = (float)(-f * 14.0 * this.minecraft.options.damageTiltStrength().get()); poseStack.mulPose(Axis.ZP.rotationDegrees(h)); poseStack.mulPose(Axis.YP.rotationDegrees(g)); } } private void bobView(PoseStack poseStack, float partialTicks) { if (this.minecraft.getCameraEntity() instanceof AbstractClientPlayer abstractClientPlayer) { float var7 = abstractClientPlayer.walkDist - abstractClientPlayer.walkDistO; float g = -(abstractClientPlayer.walkDist + var7 * partialTicks); float h = Mth.lerp(partialTicks, abstractClientPlayer.oBob, abstractClientPlayer.bob); poseStack.translate(Mth.sin(g * (float) Math.PI) * h * 0.5F, -Math.abs(Mth.cos(g * (float) Math.PI) * h), 0.0F); poseStack.mulPose(Axis.ZP.rotationDegrees(Mth.sin(g * (float) Math.PI) * h * 3.0F)); poseStack.mulPose(Axis.XP.rotationDegrees(Math.abs(Mth.cos(g * (float) Math.PI - 0.2F) * h) * 5.0F)); } } private void renderItemInHand(float partialTick, boolean sleeping, Matrix4f projectionMatrix) { if (!this.panoramicMode) { PoseStack poseStack = new PoseStack(); poseStack.pushPose(); poseStack.mulPose(projectionMatrix.invert(new Matrix4f())); Matrix4fStack matrix4fStack = RenderSystem.getModelViewStack(); matrix4fStack.pushMatrix().mul(projectionMatrix); this.bobHurt(poseStack, partialTick); if (this.minecraft.options.bobView().get()) { this.bobView(poseStack, partialTick); } if (this.minecraft.options.getCameraType().isFirstPerson() && !sleeping && !this.minecraft.options.hideGui && this.minecraft.gameMode.getPlayerMode() != GameType.SPECTATOR) { this.lightTexture.turnOnLightLayer(); this.itemInHandRenderer .renderHandsWithItems( partialTick, poseStack, this.renderBuffers.bufferSource(), this.minecraft.player, this.minecraft.getEntityRenderDispatcher().getPackedLightCoords(this.minecraft.player, partialTick) ); this.lightTexture.turnOffLightLayer(); } matrix4fStack.popMatrix(); poseStack.popPose(); } } public Matrix4f getProjectionMatrix(float fov) { Matrix4f matrix4f = new Matrix4f(); return matrix4f.perspective( fov * (float) (Math.PI / 180.0), (float)this.minecraft.getWindow().getWidth() / this.minecraft.getWindow().getHeight(), 0.05F, this.getDepthFar() ); } public float getDepthFar() { return Math.max(this.renderDistance * 4.0F, this.minecraft.options.cloudRange().get() * 16); } public static float getNightVisionScale(LivingEntity livingEntity, float nanoTime) { MobEffectInstance mobEffectInstance = livingEntity.getEffect(MobEffects.NIGHT_VISION); return !mobEffectInstance.endsWithin(200) ? 1.0F : 0.7F + Mth.sin((mobEffectInstance.getDuration() - nanoTime) * (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() || !this.minecraft.mouseHandler.isRightPressed())) { if (Util.getMillis() - this.lastActiveTime > 500L) { this.minecraft.pauseGame(false); } } else { this.lastActiveTime = Util.getMillis(); } if (!this.minecraft.noRender) { 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() ); ProfilerFiller profilerFiller = Profiler.get(); boolean bl = this.minecraft.isGameLoadFinished(); int i = (int)this.minecraft.mouseHandler.getScaledXPos(this.minecraft.getWindow()); int j = (int)this.minecraft.mouseHandler.getScaledYPos(this.minecraft.getWindow()); if (bl && renderLevel && this.minecraft.level != null) { profilerFiller.push("world"); this.renderLevel(deltaTracker); this.tryTakeScreenshotIfNeeded(); this.minecraft.levelRenderer.doEntityOutline(); if (this.postEffectId != null && this.effectActive) { RenderSystem.resetTextureMatrix(); PostChain postChain = this.minecraft.getShaderManager().getPostChain(this.postEffectId, LevelTargetBundle.MAIN_TARGETS); if (postChain != null) { postChain.process(this.minecraft.getMainRenderTarget(), this.resourcePool); } } } this.fogRenderer.endFrame(); RenderTarget renderTarget = this.minecraft.getMainRenderTarget(); RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(renderTarget.getDepthTexture(), 1.0); this.minecraft.gameRenderer.getLighting().setupFor(Lighting.Entry.ITEMS_3D); this.guiRenderState.reset(); GuiGraphics guiGraphics = new GuiGraphics(this.minecraft, this.guiRenderState); if (bl && renderLevel && this.minecraft.level != null) { profilerFiller.popPush("gui"); this.minecraft.gui.render(guiGraphics, deltaTracker); profilerFiller.pop(); } if (this.minecraft.getOverlay() != null) { try { this.minecraft.getOverlay().render(guiGraphics, i, j, deltaTracker.getGameTimeDeltaTicks()); } catch (Throwable var15) { CrashReport crashReport = CrashReport.forThrowable(var15, "Rendering overlay"); CrashReportCategory crashReportCategory = crashReport.addCategory("Overlay render details"); crashReportCategory.setDetail("Overlay name", (CrashReportDetail)(() -> this.minecraft.getOverlay().getClass().getCanonicalName())); throw new ReportedException(crashReport); } } else if (bl && this.minecraft.screen != null) { try { this.minecraft.screen.renderWithTooltip(guiGraphics, i, j, deltaTracker.getGameTimeDeltaTicks()); } catch (Throwable var14) { CrashReport crashReport = CrashReport.forThrowable(var14, "Rendering screen"); CrashReportCategory crashReportCategory = crashReport.addCategory("Screen render details"); crashReportCategory.setDetail("Screen name", (CrashReportDetail)(() -> this.minecraft.screen.getClass().getCanonicalName())); this.minecraft.mouseHandler.fillMousePositionDetails(crashReportCategory, this.minecraft.getWindow()); throw new ReportedException(crashReport); } try { if (this.minecraft.screen != null) { this.minecraft.screen.handleDelayedNarration(); } } catch (Throwable var13) { CrashReport crashReport = CrashReport.forThrowable(var13, "Narrating screen"); CrashReportCategory crashReportCategory = crashReport.addCategory("Screen details"); crashReportCategory.setDetail("Screen name", (CrashReportDetail)(() -> this.minecraft.screen.getClass().getCanonicalName())); throw new ReportedException(crashReport); } } if (bl && renderLevel && this.minecraft.level != null) { this.minecraft.gui.renderSavingIndicator(guiGraphics, deltaTracker); } if (bl) { try (Zone zone = profilerFiller.zone("toasts")) { this.minecraft.getToastManager().render(guiGraphics); } } this.guiRenderer.render(this.fogRenderer.getBuffer(FogRenderer.FogMode.NONE)); this.guiRenderer.incrementFrameNumber(); this.resourcePool.endFrame(); } } private void tryTakeScreenshotIfNeeded() { if (!this.hasWorldScreenshot && this.minecraft.isLocalServer()) { long l = Util.getMillis(); if (l - this.lastScreenshotAttempt >= 1000L) { this.lastScreenshotAttempt = l; IntegratedServer integratedServer = this.minecraft.getSingleplayerServer(); if (integratedServer != null && !integratedServer.isStopped()) { integratedServer.getWorldScreenshotFile().ifPresent(path -> { if (Files.isRegularFile(path, new LinkOption[0])) { this.hasWorldScreenshot = true; } else { this.takeAutoScreenshot(path); } }); } } } } private void takeAutoScreenshot(Path path) { if (this.minecraft.levelRenderer.countRenderedSections() > 10 && this.minecraft.levelRenderer.hasRenderedAllSections()) { Screenshot.takeScreenshot(this.minecraft.getMainRenderTarget(), nativeImage -> Util.ioPool().execute(() -> { int i = nativeImage.getWidth(); int j = nativeImage.getHeight(); int k = 0; int l = 0; if (i > j) { k = (i - j) / 2; i = j; } else { l = (j - i) / 2; j = i; } try (NativeImage nativeImage2 = new NativeImage(64, 64, false)) { nativeImage.resizeSubRectTo(k, l, i, j, nativeImage2); nativeImage2.writeToFile(path); } catch (IOException var16) { LOGGER.warn("Couldn't save auto screenshot", (Throwable)var16); } finally { nativeImage.close(); } })); } } private boolean shouldRenderBlockOutline() { if (!this.renderBlockOutline) { return false; } else { Entity entity = this.minecraft.getCameraEntity(); boolean bl = entity instanceof Player && !this.minecraft.options.hideGui; if (bl && !((Player)entity).getAbilities().mayBuild) { ItemStack itemStack = ((LivingEntity)entity).getMainHandItem(); HitResult hitResult = this.minecraft.hitResult; if (hitResult != null && hitResult.getType() == HitResult.Type.BLOCK) { BlockPos blockPos = ((BlockHitResult)hitResult).getBlockPos(); BlockState blockState = this.minecraft.level.getBlockState(blockPos); if (this.minecraft.gameMode.getPlayerMode() == GameType.SPECTATOR) { bl = blockState.getMenuProvider(this.minecraft.level, blockPos) != null; } else { BlockInWorld blockInWorld = new BlockInWorld(this.minecraft.level, blockPos, false); Registry registry = this.minecraft.level.registryAccess().lookupOrThrow(Registries.BLOCK); bl = !itemStack.isEmpty() && (itemStack.canBreakBlockInAdventureMode(blockInWorld) || itemStack.canPlaceOnBlockInAdventureMode(blockInWorld)); } } } return bl; } } public void renderLevel(DeltaTracker deltaTracker) { float f = deltaTracker.getGameTimeDeltaPartialTick(true); LocalPlayer localPlayer = this.minecraft.player; this.lightTexture.updateLightTexture(f); if (this.minecraft.getCameraEntity() == null) { this.minecraft.setCameraEntity(localPlayer); } this.pick(f); ProfilerFiller profilerFiller = Profiler.get(); profilerFiller.push("center"); boolean bl = this.shouldRenderBlockOutline(); profilerFiller.popPush("camera"); Camera camera = this.mainCamera; Entity entity = (Entity)(this.minecraft.getCameraEntity() == null ? localPlayer : this.minecraft.getCameraEntity()); float g = this.minecraft.level.tickRateManager().isEntityFrozen(entity) ? 1.0F : f; camera.setup(this.minecraft.level, entity, !this.minecraft.options.getCameraType().isFirstPerson(), this.minecraft.options.getCameraType().isMirrored(), g); this.renderDistance = this.minecraft.options.getEffectiveRenderDistance() * 16; float h = this.getFov(camera, f, true); Matrix4f matrix4f = this.getProjectionMatrix(h); PoseStack poseStack = new PoseStack(); this.bobHurt(poseStack, camera.getPartialTickTime()); if (this.minecraft.options.bobView().get()) { this.bobView(poseStack, camera.getPartialTickTime()); } matrix4f.mul(poseStack.last().pose()); float i = this.minecraft.options.screenEffectScale().get().floatValue(); float j = Mth.lerp(f, localPlayer.oPortalEffectIntensity, localPlayer.portalEffectIntensity); float k = localPlayer.getEffectBlendFactor(MobEffects.NAUSEA, f); float l = Math.max(j, k) * (i * i); if (l > 0.0F) { float m = 5.0F / (l * l + 5.0F) - l * 0.04F; m *= m; Vector3f vector3f = new Vector3f(0.0F, Mth.SQRT_OF_TWO / 2.0F, Mth.SQRT_OF_TWO / 2.0F); float n = (this.spinningEffectTime + f * this.spinningEffectSpeed) * (float) (Math.PI / 180.0); matrix4f.rotate(n, vector3f); matrix4f.scale(1.0F / m, 1.0F, 1.0F); matrix4f.rotate(-n, vector3f); } float m = Math.max(h, this.minecraft.options.fov().get().intValue()); Matrix4f matrix4f2 = this.getProjectionMatrix(m); RenderSystem.setProjectionMatrix(this.levelProjectionMatrixBuffer.getBuffer(matrix4f), ProjectionType.PERSPECTIVE); Quaternionf quaternionf = camera.rotation().conjugate(new Quaternionf()); Matrix4f matrix4f3 = new Matrix4f().rotation(quaternionf); this.minecraft.levelRenderer.prepareCullFrustum(camera.getPosition(), matrix4f3, matrix4f2); profilerFiller.popPush("fog"); boolean bl2 = this.minecraft.level.effects().isFoggyAt(camera.getBlockPosition().getX(), camera.getBlockPosition().getZ()) || this.minecraft.gui.getBossOverlay().shouldCreateWorldFog(); Vector4f vector4f = this.fogRenderer .setupFog(camera, this.minecraft.options.getEffectiveRenderDistance(), bl2, deltaTracker, this.getDarkenWorldAmount(f), this.minecraft.level); GpuBufferSlice gpuBufferSlice = this.fogRenderer.getBuffer(FogRenderer.FogMode.WORLD); profilerFiller.popPush("level"); this.minecraft.levelRenderer.renderLevel(this.resourcePool, deltaTracker, bl, camera, matrix4f3, matrix4f, gpuBufferSlice, vector4f, !bl2); profilerFiller.popPush("hand"); boolean bl3 = 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(camera, f, false)), ProjectionType.PERSPECTIVE ); RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(this.minecraft.getMainRenderTarget().getDepthTexture(), 1.0); this.renderItemInHand(f, bl3, matrix4f3); profilerFiller.popPush("screen effects"); MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource(); this.screenEffectRenderer.renderScreenEffect(bl3, f); bufferSource.endBatch(); profilerFiller.pop(); RenderSystem.setShaderFog(this.fogRenderer.getBuffer(FogRenderer.FogMode.NONE)); if (this.minecraft.gui.shouldRenderDebugCrosshair()) { this.minecraft.getDebugOverlay().render3dCrosshair(camera); } } public void resetData() { this.screenEffectRenderer.resetItemActivation(); this.minecraft.getMapTextureManager().resetData(); this.mainCamera.reset(); this.hasWorldScreenshot = false; } public void displayItemActivation(ItemStack stack) { this.screenEffectRenderer.displayItemActivation(stack, this.random); } public Minecraft getMinecraft() { return this.minecraft; } public float getDarkenWorldAmount(float partialTicks) { return Mth.lerp(partialTicks, 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 matrix4f = this.getProjectionMatrix(this.getFov(this.mainCamera, 0.0F, true)); Quaternionf quaternionf = this.mainCamera.rotation().conjugate(new Quaternionf()); Matrix4f matrix4f2 = new Matrix4f().rotation(quaternionf); Matrix4f matrix4f3 = matrix4f.mul(matrix4f2); Vec3 vec3 = this.mainCamera.getPosition(); Vec3 vec32 = point.subtract(vec3); Vector3f vector3f = matrix4f3.transformProject(vec32.toVector3f()); return new Vec3(vector3f); } @Override public double projectHorizonToScreen() { float f = this.mainCamera.getXRot(); if (f <= -90.0F) { return Double.NEGATIVE_INFINITY; } else if (f >= 90.0F) { return Double.POSITIVE_INFINITY; } else { float g = this.getFov(this.mainCamera, 0.0F, true); return Math.tan(f * (float) (Math.PI / 180.0)) / Math.tan(g / 2.0F * (float) (Math.PI / 180.0)); } } 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.effects().constantAmbientLight()); } } public PanoramaRenderer getPanorama() { return this.panorama; } }