Created
April 8, 2026 11:12
-
-
Save Ensamisten/81875d939cf29196eb0642afcaf32aa4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package io.github.ensamisten.client.screen; | |
| import com.mojang.blaze3d.platform.NativeImage; | |
| import com.mojang.blaze3d.textures.GpuSampler; | |
| import com.mojang.blaze3d.textures.GpuTextureView; | |
| import io.github.ensamisten.Allyship; | |
| import io.github.simonscholz.qrcode.QrCodeConfig; | |
| import io.github.simonscholz.qrcode.QrCodeFactory; | |
| import net.fabricmc.api.EnvType; | |
| import net.fabricmc.api.Environment; | |
| import net.minecraft.client.Minecraft; | |
| import net.minecraft.client.gui.GuiGraphicsExtractor; | |
| import net.minecraft.client.gui.screens.Screen; | |
| import net.minecraft.client.renderer.RenderPipelines; | |
| import net.minecraft.client.renderer.texture.DynamicTexture; | |
| import net.minecraft.client.renderer.texture.TextureManager; | |
| import net.minecraft.network.chat.Component; | |
| import net.minecraft.resources.Identifier; | |
| import java.awt.image.BufferedImage; | |
| import java.io.IOException; | |
| @Environment(EnvType.CLIENT) | |
| public class QrScreen extends Screen { | |
| private static final int QR_SIZE = 150; | |
| private static final int PANEL_PADDING = 16; | |
| private final String clipboard; | |
| private Identifier qrTexture; | |
| // Fields | |
| private DynamicTexture qrDynamicTexture; | |
| private Identifier qrTextureId; | |
| public QrScreen(Component title, String clipboard) { | |
| super(title); | |
| this.clipboard = clipboard; | |
| } | |
| @Override | |
| protected void init() { | |
| // Release old texture if reinitializing | |
| if (qrDynamicTexture != null) { | |
| Minecraft.getInstance().getTextureManager().release(qrTextureId); | |
| qrDynamicTexture = null; | |
| qrTextureId = null; | |
| } | |
| try { | |
| generateQrCodeImage(); | |
| } catch (Exception e) { | |
| Allyship.LOGGER.error("Failed to generate QR code", e); | |
| } | |
| } | |
| @Override | |
| public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float delta) { | |
| super.extractRenderState(graphics, mouseX, mouseY, delta); | |
| if (qrDynamicTexture == null) return; | |
| // Force GPU upload before we try to use the texture view | |
| qrDynamicTexture.upload(); | |
| GpuTextureView textureView = qrDynamicTexture.getTextureView(); | |
| GpuSampler sampler = qrDynamicTexture.getSampler(); | |
| if (textureView == null || sampler == null) return; | |
| int qrX = (this.width - QR_SIZE) / 2; | |
| int qrY = (this.height - QR_SIZE) / 2; | |
| graphics.fill( | |
| qrX - PANEL_PADDING, | |
| qrY - PANEL_PADDING, | |
| qrX + QR_SIZE + PANEL_PADDING, | |
| qrY + QR_SIZE + PANEL_PADDING, | |
| 0xCC000000 | |
| ); | |
| graphics.text( | |
| this.font, | |
| "QR Code", | |
| this.width / 2 - this.font.width("QR Code") / 2, | |
| qrY - PANEL_PADDING - this.font.lineHeight - 4, | |
| 0xFFFFFFFF, | |
| true | |
| ); | |
| // Use the GpuTextureView overload directly — avoids TextureManager lookup issues | |
| graphics.blit( | |
| textureView, | |
| sampler, | |
| qrX, // x0 | |
| qrY, // y0 | |
| qrX + QR_SIZE, // x1 | |
| qrY + QR_SIZE, // y1 | |
| 0.0f, // u0 | |
| 1.0f, // u1 | |
| 0.0f, // v0 | |
| 1.0f // v1 | |
| ); | |
| } | |
| private void generateQrCodeImage() throws IOException { | |
| QrCodeConfig config = new QrCodeConfig.Builder(clipboard) | |
| .qrCodeSize(QR_SIZE) | |
| .build(); | |
| BufferedImage bufferedImage = | |
| QrCodeFactory.createQrCodeApi().createQrCodeImage(config); | |
| NativeImage nativeImage = bufferedImageToNative(bufferedImage); | |
| qrDynamicTexture = new DynamicTexture(() -> "Allyship QR Code", nativeImage); | |
| qrTextureId = Identifier.withDefaultNamespace("allyship/qr_" + System.nanoTime()); | |
| Minecraft.getInstance().getTextureManager().register(qrTextureId, qrDynamicTexture); | |
| } | |
| private static NativeImage bufferedImageToNative(BufferedImage image) { | |
| NativeImage nativeImage = | |
| new NativeImage(NativeImage.Format.RGBA, image.getWidth(), image.getHeight(), false); | |
| for (int y = 0; y < image.getHeight(); y++) { | |
| for (int x = 0; x < image.getWidth(); x++) { | |
| int argb = image.getRGB(x, y); | |
| int a = (argb >>> 24) & 0xFF; | |
| int r = (argb >>> 16) & 0xFF; | |
| int g = (argb >>> 8) & 0xFF; | |
| int b = (argb) & 0xFF; | |
| int abgr = (a << 24) | (b << 16) | (g << 8) | r; | |
| nativeImage.setPixel(x, y, abgr); | |
| } | |
| } | |
| return nativeImage; | |
| } | |
| @Override | |
| public boolean isPauseScreen() { | |
| return false; | |
| } | |
| @Override | |
| public void onClose() { | |
| super.onClose(); | |
| if (qrTexture != null) { | |
| Minecraft.getInstance() | |
| .getTextureManager() | |
| .release(qrTexture); | |
| qrTexture = null; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment