/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.mojang.logging.LogUtils * org.jspecify.annotations.Nullable * org.slf4j.Logger */ package net.minecraft.client; import com.mojang.blaze3d.buffers.GpuBuffer; import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.systems.CommandEncoder; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.textures.GpuTexture; import com.mojang.logging.LogUtils; import java.io.File; import java.util.function.Consumer; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.ARGB; import net.minecraft.util.Util; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; public class Screenshot { private static final Logger LOGGER = LogUtils.getLogger(); public static final String SCREENSHOT_DIR = "screenshots"; public static void grab(File workDir, RenderTarget target, Consumer callback) { Screenshot.grab(workDir, null, target, 1, callback); } public static void grab(File workDir, @Nullable String forceName, RenderTarget target, int downscaleFactor, Consumer callback) { Screenshot.takeScreenshot(target, downscaleFactor, image -> { File picDir = new File(workDir, SCREENSHOT_DIR); picDir.mkdir(); File file = forceName == null ? Screenshot.getFile(picDir) : new File(picDir, forceName); Util.ioPool().execute(() -> { try (NativeImage nativeImage = image;){ image.writeToFile(file); MutableComponent component = Component.literal(file.getName()).withStyle(ChatFormatting.UNDERLINE).withStyle(s -> s.withClickEvent(new ClickEvent.OpenFile(file.getAbsoluteFile()))); callback.accept(Component.translatable("screenshot.success", component)); } catch (Exception e) { LOGGER.warn("Couldn't save screenshot", (Throwable)e); callback.accept(Component.translatable("screenshot.failure", e.getMessage())); } }); }); } public static void takeScreenshot(RenderTarget target, Consumer callback) { Screenshot.takeScreenshot(target, 1, callback); } public static void takeScreenshot(RenderTarget target, int downscaleFactor, Consumer callback) { int width = target.width; int height = target.height; GpuTexture sourceTexture = target.getColorTexture(); if (sourceTexture == null) { throw new IllegalStateException("Tried to capture screenshot of an incomplete framebuffer"); } if (width % downscaleFactor != 0 || height % downscaleFactor != 0) { throw new IllegalArgumentException("Image size is not divisible by downscale factor"); } GpuBuffer buffer = RenderSystem.getDevice().createBuffer(() -> "Screenshot buffer", 9, width * height * sourceTexture.getFormat().pixelSize()); CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder(); RenderSystem.getDevice().createCommandEncoder().copyTextureToBuffer(sourceTexture, buffer, 0, () -> { try (GpuBuffer.MappedView read = commandEncoder.mapBuffer(buffer, true, false);){ int outputHeight = height / downscaleFactor; int outputWidth = width / downscaleFactor; NativeImage image = new NativeImage(outputWidth, outputHeight, false); for (int y = 0; y < outputHeight; ++y) { for (int x = 0; x < outputWidth; ++x) { if (downscaleFactor == 1) { int argb = read.data().getInt((x + y * width) * sourceTexture.getFormat().pixelSize()); image.setPixelABGR(x, height - y - 1, argb | 0xFF000000); continue; } int red = 0; int green = 0; int blue = 0; for (int i = 0; i < downscaleFactor; ++i) { for (int j = 0; j < downscaleFactor; ++j) { int argb = read.data().getInt((x * downscaleFactor + i + (y * downscaleFactor + j) * width) * sourceTexture.getFormat().pixelSize()); red += ARGB.red(argb); green += ARGB.green(argb); blue += ARGB.blue(argb); } } int sampleCount = downscaleFactor * downscaleFactor; image.setPixelABGR(x, outputHeight - y - 1, ARGB.color(255, red / sampleCount, green / sampleCount, blue / sampleCount)); } } callback.accept(image); } buffer.close(); }, 0); } private static File getFile(File picDir) { String name = Util.getFilenameFormattedDateTime(); int count = 1; File file; while ((file = new File(picDir, name + (String)(count == 1 ? "" : "_" + count) + ".png")).exists()) { ++count; } return file; } }