src/main/java/wtf/sten/vault/Shot.java
package wtf.sten.vault;
import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.NativeImage;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Screenshot;
import java.nio.file.Files;
import java.nio.file.Path;
public final class Shot {
private static final int MAX_BYTES = 180_000;
private Shot() {
}
public static void capture(Minecraft mc, String kind) {
try {
if (mc == null || mc.gameRenderer == null) return;
RenderTarget target = mc.gameRenderer.mainRenderTarget();
if (target == null || target.width < 2 || target.height < 2) return;
int factor = downscale(target.width, target.height);
Screenshot.takeScreenshot(target, factor, image -> write(image, kind));
} catch (Exception ignored) {
}
}
static int downscale(int width, int height) {
for (int factor : new int[]{8, 4, 2}) {
if (width % factor == 0 && height % factor == 0) return factor;
}
return 1;
}
private static void write(NativeImage image, String kind) {
NativeImage current = image;
try {
int guard = 0;
while (true) {
Path tmp = FabricLoader.getInstance().getGameDir().resolve("sten-vault-shot.png");
current.writeToFile(tmp);
byte[] bytes = Files.readAllBytes(tmp);
Files.deleteIfExists(tmp);
if (bytes.length <= MAX_BYTES || current.getWidth() <= 160 || guard++ > 4) {
if (bytes.length <= MAX_BYTES) {
StenNet.uploadShot(kind == null || kind.isBlank() ? "auto" : kind, bytes);
}
return;
}
NativeImage next = shrink(current);
if (next == current) return;
if (current != image) current.close();
current = next;
}
} catch (Exception ignored) {
} finally {
if (current != null && current != image) current.close();
image.close();
}
}
private static NativeImage shrink(NativeImage src) {
int width = Math.max(160, src.getWidth() / 2);
int height = Math.max(1, src.getHeight() * width / src.getWidth());
if (width >= src.getWidth()) return src;
NativeImage dst = new NativeImage(width, height, false);
src.resizeSubRectTo(0, 0, src.getWidth(), src.getHeight(), dst);
return dst;
}
}