package net.minecraft.client.renderer; import com.mojang.blaze3d.ProjectionType; import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.platform.Window; 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.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.player.AbstractClientPlayer; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource.BufferSource; 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.ResourceManager; 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.ItemDisplayContext; 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.phys.HitResult.Type; 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.slf4j.Logger; @Environment(EnvType.CLIENT) public class GameRenderer implements 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; private static final float GUI_Z_NEAR = 1000.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 ResourceManager resourceManager; private final RandomSource random = RandomSource.create(); private float renderDistance; public final ItemInHandRenderer itemInHandRenderer; private final RenderBuffers renderBuffers; private float spinningEffectTime; private float spinningEffectSpeed; private float fovModifier; private float oldFovModifier; private float darkenWorldAmount; private float darkenWorldAmountO; private boolean renderHand = true; 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; private float zoom = 1.0F; private float zoomX; private float zoomY; public static final int ITEM_ACTIVATION_ANIMATION_LENGTH = 40; @Nullable private ItemStack itemActivationItem; private int itemActivationTicks; private float itemActivationOffX; private float itemActivationOffY; private final CrossFrameResourcePool resourcePool = new CrossFrameResourcePool(3); @Nullable private ResourceLocation postEffectId; private boolean effectActive; private final Camera mainCamera = new Camera(); public GameRenderer(Minecraft minecraft, ItemInHandRenderer itemInHandRenderer, ResourceManager resourceManager, RenderBuffers renderBuffers) { this.minecraft = minecraft; this.resourceManager = resourceManager; this.itemInHandRenderer = itemInHandRenderer; this.lightTexture = new LightTexture(this, minecraft); this.renderBuffers = renderBuffers; } public void close() { this.lightTexture.close(); this.overlayTexture.close(); this.resourcePool.close(); } public void setRenderHand(boolean renderHand) { this.renderHand = renderHand; } 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() { float f = this.minecraft.options.getMenuBackgroundBlurriness(); if (!(f < 1.0F)) { PostChain postChain = this.minecraft.getShaderManager().getPostChain(BLUR_POST_CHAIN_ID, LevelTargetBundle.MAIN_TARGETS); if (postChain != null) { postChain.process(this.minecraft.getMainRenderTarget(), this.resourcePool, renderPass -> renderPass.setUniform("Radius", f)); } } } 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_OVERLAY, biFunction); gpuDevice.precompilePipeline(RenderPipelines.GUI_TEXTURED_OVERLAY, 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; } if (this.itemActivationTicks > 0) { this.itemActivationTicks--; if (this.itemActivationTicks == 0) { this.itemActivationItem = null; } } } } @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() != 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)); } } public void renderZoomed(float zoom, float zoomX, float zoomY) { this.zoom = zoom; this.zoomX = zoomX; this.zoomY = zoomY; this.setRenderBlockOutline(false); this.setRenderHand(false); this.renderLevel(DeltaTracker.ZERO); this.zoom = 1.0F; } private void renderItemInHand(Camera camera, float partialTick, Matrix4f projectionMatrix) { if (!this.panoramicMode) { Matrix4f matrix4f = this.getProjectionMatrix(this.getFov(camera, partialTick, false)); RenderSystem.setProjectionMatrix(matrix4f, ProjectionType.PERSPECTIVE); 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); } boolean bl = this.minecraft.getCameraEntity() instanceof LivingEntity && ((LivingEntity)this.minecraft.getCameraEntity()).isSleeping(); if (this.minecraft.options.getCameraType().isFirstPerson() && !bl && !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(); if (this.minecraft.options.getCameraType().isFirstPerson() && !bl) { BufferSource bufferSource = this.renderBuffers.bufferSource(); ScreenEffectRenderer.renderScreenEffect(this.minecraft, poseStack, bufferSource); bufferSource.endBatch(); } } } public Matrix4f getProjectionMatrix(float fov) { Matrix4f matrix4f = new Matrix4f(); if (this.zoom != 1.0F) { matrix4f.translate(this.zoomX, -this.zoomY, 0.0F); matrix4f.scale(this.zoom, this.zoom, 1.0F); } 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 this.renderDistance * 4.0F; } 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) { 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("level"); 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, null); } } } Window window = this.minecraft.getWindow(); RenderTarget renderTarget = this.minecraft.getMainRenderTarget(); RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(renderTarget.getDepthTexture(), 1.0); Matrix4f matrix4f = new Matrix4f() .setOrtho(0.0F, (float)(window.getWidth() / window.getGuiScale()), (float)(window.getHeight() / window.getGuiScale()), 0.0F, 1000.0F, 21000.0F); RenderSystem.setProjectionMatrix(matrix4f, ProjectionType.ORTHOGRAPHIC); Matrix4fStack matrix4fStack = RenderSystem.getModelViewStack(); matrix4fStack.pushMatrix(); matrix4fStack.translation(0.0F, 0.0F, -11000.0F); Lighting.setupFor3DItems(); GuiGraphics guiGraphics = new GuiGraphics(this.minecraft, this.renderBuffers.bufferSource()); if (bl && renderLevel && this.minecraft.level != null) { profilerFiller.popPush("gui"); if (!this.minecraft.options.hideGui) { this.renderItemActivationAnimation(guiGraphics, deltaTracker.getGameTimeDeltaPartialTick(false)); } this.minecraft.gui.render(guiGraphics, deltaTracker); guiGraphics.flush(); RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(renderTarget.getDepthTexture(), 1.0); profilerFiller.pop(); } if (this.minecraft.getOverlay() != null) { try { this.minecraft.getOverlay().render(guiGraphics, i, j, deltaTracker.getGameTimeDeltaTicks()); } catch (Throwable var18) { CrashReport crashReport = CrashReport.forThrowable(var18, "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 var17) { CrashReport crashReport = CrashReport.forThrowable(var17, "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 var16) { CrashReport crashReport = CrashReport.forThrowable(var16, "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); } } guiGraphics.flush(); matrix4fStack.popMatrix(); 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() == 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(matrix4f, ProjectionType.PERSPECTIVE); Quaternionf quaternionf = camera.rotation().conjugate(new Quaternionf()); Matrix4f matrix4f3 = new Matrix4f().rotation(quaternionf); this.minecraft.levelRenderer.prepareCullFrustum(camera.getPosition(), matrix4f3, matrix4f2); this.minecraft.levelRenderer.renderLevel(this.resourcePool, deltaTracker, bl, camera, this, matrix4f3, matrix4f); profilerFiller.popPush("hand"); if (this.renderHand) { RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(this.minecraft.getMainRenderTarget().getDepthTexture(), 1.0); this.renderItemInHand(camera, f, matrix4f3); } profilerFiller.pop(); } public void resetData() { this.itemActivationItem = null; this.minecraft.getMapTextureManager().resetData(); this.mainCamera.reset(); this.hasWorldScreenshot = false; } public void displayItemActivation(ItemStack stack) { this.itemActivationItem = stack; this.itemActivationTicks = 40; this.itemActivationOffX = this.random.nextFloat() * 2.0F - 1.0F; this.itemActivationOffY = this.random.nextFloat() * 2.0F - 1.0F; } private void renderItemActivationAnimation(GuiGraphics guiGraphics, float partialTick) { if (this.itemActivationItem != null && this.itemActivationTicks > 0) { int i = 40 - this.itemActivationTicks; float f = (i + partialTick) / 40.0F; float g = f * f; float h = f * g; float j = 10.25F * h * g - 24.95F * g * g + 25.5F * h - 13.8F * g + 4.0F * f; float k = j * (float) Math.PI; float l = this.itemActivationOffX * (guiGraphics.guiWidth() / 4); float m = this.itemActivationOffY * (guiGraphics.guiHeight() / 4); PoseStack poseStack = guiGraphics.pose(); poseStack.pushPose(); poseStack.translate(guiGraphics.guiWidth() / 2 + l * Mth.abs(Mth.sin(k * 2.0F)), guiGraphics.guiHeight() / 2 + m * Mth.abs(Mth.sin(k * 2.0F)), -50.0F); float n = 50.0F + 175.0F * Mth.sin(k); poseStack.scale(n, -n, n); poseStack.mulPose(Axis.YP.rotationDegrees(900.0F * Mth.abs(Mth.sin(k)))); poseStack.mulPose(Axis.XP.rotationDegrees(6.0F * Mth.cos(f * 8.0F))); poseStack.mulPose(Axis.ZP.rotationDegrees(6.0F * Mth.cos(f * 8.0F))); guiGraphics.drawSpecial( multiBufferSource -> this.minecraft .getItemRenderer() .renderStatic( this.itemActivationItem, ItemDisplayContext.FIXED, 15728880, OverlayTexture.NO_OVERLAY, poseStack, multiBufferSource, this.minecraft.level, 0 ) ); poseStack.popPose(); } } 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; } }