/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.base.Strings * com.mojang.datafixers.DataFixUtils * org.joml.Matrix4f * org.joml.Matrix4fStack * org.joml.Matrix4fc * org.joml.Vector3f * org.joml.Vector3fc * org.joml.Vector4f * org.joml.Vector4fc * org.jspecify.annotations.Nullable */ package net.minecraft.client.gui.components; import com.google.common.base.Strings; import com.mojang.blaze3d.buffers.GpuBuffer; import com.mojang.blaze3d.buffers.GpuBufferSlice; import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.systems.RenderPass; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.textures.GpuTextureView; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.MeshData; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.datafixers.DataFixUtils; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.OptionalDouble; import java.util.OptionalInt; import java.util.concurrent.CompletableFuture; import net.minecraft.client.Camera; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.Options; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.debug.DebugScreenDisplayer; import net.minecraft.client.gui.components.debug.DebugScreenEntries; import net.minecraft.client.gui.components.debug.DebugScreenEntry; import net.minecraft.client.gui.components.debug.DebugScreenEntryList; import net.minecraft.client.gui.components.debugchart.BandwidthDebugChart; import net.minecraft.client.gui.components.debugchart.FpsDebugChart; import net.minecraft.client.gui.components.debugchart.PingDebugChart; import net.minecraft.client.gui.components.debugchart.ProfilerPieChart; import net.minecraft.client.gui.components.debugchart.TpsDebugChart; import net.minecraft.client.gui.screens.LevelLoadingScreen; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.server.IntegratedServer; import net.minecraft.core.BlockPos; import net.minecraft.resources.Identifier; import net.minecraft.server.level.ChunkLevel; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.progress.ChunkLoadStatusView; import net.minecraft.util.debugchart.LocalSampleLogger; import net.minecraft.util.debugchart.RemoteDebugSampleType; import net.minecraft.util.debugchart.TpsDebugDimensions; import net.minecraft.util.profiling.Profiler; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.util.profiling.Zone; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.status.ChunkStatus; import org.joml.Matrix4f; import org.joml.Matrix4fStack; import org.joml.Matrix4fc; import org.joml.Vector3f; import org.joml.Vector3fc; import org.joml.Vector4f; import org.joml.Vector4fc; import org.jspecify.annotations.Nullable; public class DebugScreenOverlay { private static final float CROSSHAIR_SCALE = 0.01f; private static final int CROSSHAIR_INDEX_COUNT = 36; private static final int MARGIN_RIGHT = 2; private static final int MARGIN_LEFT = 2; private static final int MARGIN_TOP = 2; private final Minecraft minecraft; private final Font font; private final GpuBuffer crosshairBuffer; private final RenderSystem.AutoStorageIndexBuffer crosshairIndicies = RenderSystem.getSequentialBuffer(VertexFormat.Mode.LINES); private @Nullable ChunkPos lastPos; private @Nullable LevelChunk clientChunk; private @Nullable CompletableFuture serverChunk; private boolean renderProfilerChart; private boolean renderFpsCharts; private boolean renderNetworkCharts; private final LocalSampleLogger frameTimeLogger = new LocalSampleLogger(1); private final LocalSampleLogger tickTimeLogger = new LocalSampleLogger(TpsDebugDimensions.values().length); private final LocalSampleLogger pingLogger = new LocalSampleLogger(1); private final LocalSampleLogger bandwidthLogger = new LocalSampleLogger(1); private final Map remoteSupportingLoggers = Map.of(RemoteDebugSampleType.TICK_TIME, this.tickTimeLogger); private final FpsDebugChart fpsChart; private final TpsDebugChart tpsChart; private final PingDebugChart pingChart; private final BandwidthDebugChart bandwidthChart; private final ProfilerPieChart profilerPieChart; public DebugScreenOverlay(Minecraft minecraft) { this.minecraft = minecraft; this.font = minecraft.font; this.fpsChart = new FpsDebugChart(this.font, this.frameTimeLogger); this.tpsChart = new TpsDebugChart(this.font, this.tickTimeLogger, () -> Float.valueOf(minecraft.level == null ? 0.0f : minecraft.level.tickRateManager().millisecondsPerTick())); this.pingChart = new PingDebugChart(this.font, this.pingLogger); this.bandwidthChart = new BandwidthDebugChart(this.font, this.bandwidthLogger); this.profilerPieChart = new ProfilerPieChart(this.font); try (ByteBufferBuilder byteBufferBuilder = ByteBufferBuilder.exactlySized(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH.getVertexSize() * 12 * 2);){ BufferBuilder bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH); bufferBuilder.addVertex(0.0f, 0.0f, 0.0f).setColor(-16777216).setNormal(1.0f, 0.0f, 0.0f).setLineWidth(4.0f); bufferBuilder.addVertex(1.0f, 0.0f, 0.0f).setColor(-16777216).setNormal(1.0f, 0.0f, 0.0f).setLineWidth(4.0f); bufferBuilder.addVertex(0.0f, 0.0f, 0.0f).setColor(-16777216).setNormal(0.0f, 1.0f, 0.0f).setLineWidth(4.0f); bufferBuilder.addVertex(0.0f, 1.0f, 0.0f).setColor(-16777216).setNormal(0.0f, 1.0f, 0.0f).setLineWidth(4.0f); bufferBuilder.addVertex(0.0f, 0.0f, 0.0f).setColor(-16777216).setNormal(0.0f, 0.0f, 1.0f).setLineWidth(4.0f); bufferBuilder.addVertex(0.0f, 0.0f, 1.0f).setColor(-16777216).setNormal(0.0f, 0.0f, 1.0f).setLineWidth(4.0f); bufferBuilder.addVertex(0.0f, 0.0f, 0.0f).setColor(-65536).setNormal(1.0f, 0.0f, 0.0f).setLineWidth(2.0f); bufferBuilder.addVertex(1.0f, 0.0f, 0.0f).setColor(-65536).setNormal(1.0f, 0.0f, 0.0f).setLineWidth(2.0f); bufferBuilder.addVertex(0.0f, 0.0f, 0.0f).setColor(-16711936).setNormal(0.0f, 1.0f, 0.0f).setLineWidth(2.0f); bufferBuilder.addVertex(0.0f, 1.0f, 0.0f).setColor(-16711936).setNormal(0.0f, 1.0f, 0.0f).setLineWidth(2.0f); bufferBuilder.addVertex(0.0f, 0.0f, 0.0f).setColor(-8421377).setNormal(0.0f, 0.0f, 1.0f).setLineWidth(2.0f); bufferBuilder.addVertex(0.0f, 0.0f, 1.0f).setColor(-8421377).setNormal(0.0f, 0.0f, 1.0f).setLineWidth(2.0f); try (MeshData meshData = bufferBuilder.buildOrThrow();){ this.crosshairBuffer = RenderSystem.getDevice().createBuffer(() -> "Crosshair vertex buffer", 32, meshData.vertexBuffer()); } } } public void clearChunkCache() { this.serverChunk = null; this.clientChunk = null; } public void render(GuiGraphics graphics) { IntegratedServer singleplayerServer; ArrayList finalGroups; ChunkPos chunkPos; Options options = this.minecraft.options; if (!this.minecraft.isGameLoadFinished() || options.hideGui && this.minecraft.screen == null) { return; } Collection visibleEntries = this.minecraft.debugEntries.getCurrentlyEnabled(); if (visibleEntries.isEmpty()) { return; } graphics.nextStratum(); ProfilerFiller profiler = Profiler.get(); profiler.push("debug"); if (this.minecraft.getCameraEntity() != null && this.minecraft.level != null) { BlockPos feetPos = this.minecraft.getCameraEntity().blockPosition(); chunkPos = new ChunkPos(feetPos); } else { chunkPos = null; } if (!Objects.equals(this.lastPos, chunkPos)) { this.lastPos = chunkPos; this.clearChunkCache(); } final ArrayList leftLines = new ArrayList(); final ArrayList rightLines = new ArrayList(); final LinkedHashMap groups = new LinkedHashMap(); final ArrayList regularLines = new ArrayList(); DebugScreenDisplayer displayer = new DebugScreenDisplayer(){ @Override public void addPriorityLine(String line) { if (leftLines.size() > rightLines.size()) { rightLines.add(line); } else { leftLines.add(line); } } @Override public void addLine(String line) { regularLines.add(line); } @Override public void addToGroup(Identifier group, Collection lines) { groups.computeIfAbsent(group, k -> new ArrayList()).addAll(lines); } @Override public void addToGroup(Identifier group, String lines) { groups.computeIfAbsent(group, k -> new ArrayList()).add(lines); } }; Level level = this.getLevel(); for (Identifier id : visibleEntries) { DebugScreenEntry entry = DebugScreenEntries.getEntry(id); if (entry == null) continue; entry.display(displayer, level, this.getClientChunk(), this.getServerChunk()); } if (!leftLines.isEmpty()) { leftLines.add(""); } if (!rightLines.isEmpty()) { rightLines.add(""); } if (!regularLines.isEmpty()) { int mid = (regularLines.size() + 1) / 2; leftLines.addAll(regularLines.subList(0, mid)); rightLines.addAll(regularLines.subList(mid, regularLines.size())); leftLines.add(""); if (mid < regularLines.size()) { rightLines.add(""); } } if (!(finalGroups = new ArrayList(groups.values())).isEmpty()) { int mid = (finalGroups.size() + 1) / 2; for (int i = 0; i < finalGroups.size(); ++i) { Collection lines = (Collection)finalGroups.get(i); if (lines.isEmpty()) continue; if (i < mid) { leftLines.addAll(lines); leftLines.add(""); continue; } rightLines.addAll(lines); rightLines.add(""); } } if (this.minecraft.debugEntries.isOverlayVisible()) { leftLines.add(""); boolean hasServer = this.minecraft.getSingleplayerServer() != null; KeyMapping keyDebugModifier = options.keyDebugModifier; String modifierBind = keyDebugModifier.getTranslatedKeyMessage().getString(); String bindOutputPrefix = "[" + (String)(keyDebugModifier.isUnbound() ? "" : modifierBind + "+"); String profilerBind = bindOutputPrefix + options.keyDebugPofilingChart.getTranslatedKeyMessage().getString() + "]"; String fpsBind = bindOutputPrefix + options.keyDebugFpsCharts.getTranslatedKeyMessage().getString() + "]"; String networkBind = bindOutputPrefix + options.keyDebugNetworkCharts.getTranslatedKeyMessage().getString() + "]"; leftLines.add("Debug charts: " + profilerBind + " Profiler " + (this.renderProfilerChart ? "visible" : "hidden") + "; " + fpsBind + " " + (hasServer ? "FPS + TPS " : "FPS ") + (this.renderFpsCharts ? "visible" : "hidden") + "; " + networkBind + " " + (!this.minecraft.isLocalServer() ? "Bandwidth + Ping" : "Ping") + (this.renderNetworkCharts ? " visible" : " hidden")); String optionsBind = bindOutputPrefix + options.keyDebugDebugOptions.getTranslatedKeyMessage().getString() + "]"; leftLines.add("To edit: press " + optionsBind); } this.renderLines(graphics, leftLines, true); this.renderLines(graphics, rightLines, false); graphics.nextStratum(); this.profilerPieChart.setBottomOffset(10); if (this.showFpsCharts()) { int scaledWidth = graphics.guiWidth(); int maxWidth = scaledWidth / 2; this.fpsChart.drawChart(graphics, 0, this.fpsChart.getWidth(maxWidth)); if (this.tickTimeLogger.size() > 0) { int width = this.tpsChart.getWidth(maxWidth); this.tpsChart.drawChart(graphics, scaledWidth - width, width); } this.profilerPieChart.setBottomOffset(this.tpsChart.getFullHeight()); } if (this.showNetworkCharts() && this.minecraft.getConnection() != null) { int scaledWidth = graphics.guiWidth(); int maxWidth = scaledWidth / 2; if (!this.minecraft.isLocalServer()) { this.bandwidthChart.drawChart(graphics, 0, this.bandwidthChart.getWidth(maxWidth)); } int width = this.pingChart.getWidth(maxWidth); this.pingChart.drawChart(graphics, scaledWidth - width, width); this.profilerPieChart.setBottomOffset(this.pingChart.getFullHeight()); } if (this.minecraft.debugEntries.isCurrentlyEnabled(DebugScreenEntries.VISUALIZE_CHUNKS_ON_SERVER) && (singleplayerServer = this.minecraft.getSingleplayerServer()) != null && this.minecraft.player != null) { ChunkLoadStatusView statusView = singleplayerServer.createChunkLoadStatusView(16 + ChunkLevel.RADIUS_AROUND_FULL_CHUNK); statusView.moveTo(this.minecraft.player.level().dimension(), this.minecraft.player.chunkPosition()); LevelLoadingScreen.renderChunks(graphics, graphics.guiWidth() / 2, graphics.guiHeight() / 2, 4, 1, statusView); } try (Zone ignored = profiler.zone("profilerPie");){ this.profilerPieChart.render(graphics); } profiler.pop(); } private void renderLines(GuiGraphics graphics, List lines, boolean alignLeft) { int top; int left; int width; String line; int i; int height = this.font.lineHeight; for (i = 0; i < lines.size(); ++i) { line = lines.get(i); if (Strings.isNullOrEmpty((String)line)) continue; width = this.font.width(line); left = alignLeft ? 2 : graphics.guiWidth() - 2 - width; top = 2 + height * i; graphics.fill(left - 1, top - 1, left + width + 1, top + height - 1, -1873784752); } for (i = 0; i < lines.size(); ++i) { line = lines.get(i); if (Strings.isNullOrEmpty((String)line)) continue; width = this.font.width(line); left = alignLeft ? 2 : graphics.guiWidth() - 2 - width; top = 2 + height * i; graphics.drawString(this.font, line, left, top, -2039584, false); } } private @Nullable ServerLevel getServerLevel() { if (this.minecraft.level == null) { return null; } IntegratedServer server = this.minecraft.getSingleplayerServer(); if (server != null) { return server.getLevel(this.minecraft.level.dimension()); } return null; } private @Nullable Level getLevel() { if (this.minecraft.level == null) { return null; } return (Level)DataFixUtils.orElse(Optional.ofNullable(this.minecraft.getSingleplayerServer()).flatMap(s -> Optional.ofNullable(s.getLevel(this.minecraft.level.dimension()))), (Object)this.minecraft.level); } private @Nullable LevelChunk getServerChunk() { if (this.minecraft.level == null || this.lastPos == null) { return null; } if (this.serverChunk == null) { ServerLevel level = this.getServerLevel(); if (level == null) { return null; } this.serverChunk = level.getChunkSource().getChunkFuture(this.lastPos.x, this.lastPos.z, ChunkStatus.FULL, false).thenApply(chunkResult -> chunkResult.orElse(null)); } return this.serverChunk.getNow(null); } private @Nullable LevelChunk getClientChunk() { if (this.minecraft.level == null || this.lastPos == null) { return null; } if (this.clientChunk == null) { this.clientChunk = this.minecraft.level.getChunk(this.lastPos.x, this.lastPos.z); } return this.clientChunk; } public boolean showDebugScreen() { DebugScreenEntryList entries = this.minecraft.debugEntries; return !(!entries.isOverlayVisible() && entries.getCurrentlyEnabled().isEmpty() || this.minecraft.options.hideGui && this.minecraft.screen == null); } public boolean showProfilerChart() { return this.minecraft.debugEntries.isOverlayVisible() && this.renderProfilerChart; } public boolean showNetworkCharts() { return this.minecraft.debugEntries.isOverlayVisible() && this.renderNetworkCharts; } public boolean showFpsCharts() { return this.minecraft.debugEntries.isOverlayVisible() && this.renderFpsCharts; } public void toggleNetworkCharts() { boolean bl = this.renderNetworkCharts = !this.minecraft.debugEntries.isOverlayVisible() || !this.renderNetworkCharts; if (this.renderNetworkCharts) { this.minecraft.debugEntries.setOverlayVisible(true); this.renderFpsCharts = false; } } public void toggleFpsCharts() { boolean bl = this.renderFpsCharts = !this.minecraft.debugEntries.isOverlayVisible() || !this.renderFpsCharts; if (this.renderFpsCharts) { this.minecraft.debugEntries.setOverlayVisible(true); this.renderNetworkCharts = false; } } public void toggleProfilerChart() { boolean bl = this.renderProfilerChart = !this.minecraft.debugEntries.isOverlayVisible() || !this.renderProfilerChart; if (this.renderProfilerChart) { this.minecraft.debugEntries.setOverlayVisible(true); } } public void logFrameDuration(long frameDuration) { this.frameTimeLogger.logSample(frameDuration); } public LocalSampleLogger getTickTimeLogger() { return this.tickTimeLogger; } public LocalSampleLogger getPingLogger() { return this.pingLogger; } public LocalSampleLogger getBandwidthLogger() { return this.bandwidthLogger; } public ProfilerPieChart getProfilerPieChart() { return this.profilerPieChart; } public void logRemoteSample(long[] sample, RemoteDebugSampleType type) { LocalSampleLogger logger = this.remoteSupportingLoggers.get((Object)type); if (logger != null) { logger.logFullSample(sample); } } public void reset() { this.tickTimeLogger.reset(); this.pingLogger.reset(); this.bandwidthLogger.reset(); } public void render3dCrosshair(Camera camera) { Matrix4fStack modelViewStack = RenderSystem.getModelViewStack(); modelViewStack.pushMatrix(); modelViewStack.translate(0.0f, 0.0f, -1.0f); modelViewStack.rotateX(camera.xRot() * ((float)Math.PI / 180)); modelViewStack.rotateY(camera.yRot() * ((float)Math.PI / 180)); float crosshairScale = 0.01f * (float)this.minecraft.getWindow().getGuiScale(); modelViewStack.scale(-crosshairScale, crosshairScale, -crosshairScale); RenderPipeline renderPipeline = RenderPipelines.LINES; RenderTarget mainRenderTarget = Minecraft.getInstance().getMainRenderTarget(); GpuTextureView colorTexture = mainRenderTarget.getColorTextureView(); GpuTextureView depthTexture = mainRenderTarget.getDepthTextureView(); GpuBuffer indexBuffer = this.crosshairIndicies.getBuffer(36); GpuBufferSlice dynamicTransform = RenderSystem.getDynamicUniforms().writeTransform((Matrix4fc)modelViewStack, (Vector4fc)new Vector4f(1.0f, 1.0f, 1.0f, 1.0f), (Vector3fc)new Vector3f(), (Matrix4fc)new Matrix4f()); try (RenderPass renderPass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(() -> "3d crosshair", colorTexture, OptionalInt.empty(), depthTexture, OptionalDouble.empty());){ renderPass.setPipeline(renderPipeline); RenderSystem.bindDefaultUniforms(renderPass); renderPass.setVertexBuffer(0, this.crosshairBuffer); renderPass.setIndexBuffer(indexBuffer, this.crosshairIndicies.type()); renderPass.setUniform("DynamicTransforms", dynamicTransform); renderPass.drawIndexed(0, 0, 36, 1); } modelViewStack.popMatrix(); } }