From 89938d618307955ac1218b0f286bb1b1ce252e35 Mon Sep 17 00:00:00 2001 From: nextdaydelivery <79922345+nxtdaydelivery@users.noreply.github.com> Date: Mon, 11 Jul 2022 13:45:16 +0100 Subject: hippity hoppity oneconfig is my property --- .../cc/woverflow/chatting/utils/RenderUtils.kt | 259 +++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 src/main/kotlin/cc/woverflow/chatting/utils/RenderUtils.kt (limited to 'src/main/kotlin/cc/woverflow/chatting/utils/RenderUtils.kt') diff --git a/src/main/kotlin/cc/woverflow/chatting/utils/RenderUtils.kt b/src/main/kotlin/cc/woverflow/chatting/utils/RenderUtils.kt new file mode 100644 index 0000000..12051cf --- /dev/null +++ b/src/main/kotlin/cc/woverflow/chatting/utils/RenderUtils.kt @@ -0,0 +1,259 @@ +@file:JvmName("RenderUtils") + +package cc.woverflow.chatting.utils + +import cc.polyfrost.oneconfig.utils.IOUtils +import cc.woverflow.chatting.config.ChattingConfig +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.client.renderer.texture.TextureUtil +import net.minecraft.client.shader.Framebuffer +import org.apache.commons.lang3.SystemUtils +import org.lwjgl.BufferUtils +import org.lwjgl.opengl.GL11 +import org.lwjgl.opengl.GL12 +import sun.awt.datatransfer.DataTransferer +import sun.awt.datatransfer.SunClipboard +import java.awt.Toolkit +import java.awt.image.BufferedImage +import java.io.File +import java.lang.reflect.Field +import java.lang.reflect.Method +import java.nio.ByteBuffer +import java.nio.ByteOrder +import javax.imageio.ImageIO + +/** + * Taken from https://github.com/Moulberry/HyChat + */ +fun createBindFramebuffer(w: Int, h: Int): Framebuffer { + val framebuffer = Framebuffer(w, h, false) + framebuffer.framebufferColor[0] = 0x36 / 255f + framebuffer.framebufferColor[1] = 0x39 / 255f + framebuffer.framebufferColor[2] = 0x3F / 255f + framebuffer.framebufferClear() + GlStateManager.matrixMode(5889) + GlStateManager.loadIdentity() + GlStateManager.ortho(0.0, w.toDouble(), h.toDouble(), 0.0, 1000.0, 3000.0) + GlStateManager.matrixMode(5888) + GlStateManager.loadIdentity() + GlStateManager.translate(0.0f, 0.0f, -2000.0f) + framebuffer.bindFramebuffer(true) + return framebuffer +} + +/** + * Taken from https://github.com/Moulberry/HyChat + * Modified so if not on Windows just in case it will switch it to RGB and remove the transparent background. + */ +fun BufferedImage.copyToClipboard() { + if (SystemUtils.IS_OS_WINDOWS) { + try { + val width = this.width + val height = this.height + val hdrSize = 0x28 + val buffer: ByteBuffer = ByteBuffer.allocate(hdrSize + width * height * 4) + buffer.order(ByteOrder.LITTLE_ENDIAN) + //Header size + buffer.putInt(hdrSize) + //Width + buffer.putInt(width) + //Int32 biHeight; + buffer.putInt(height) + //Int16 biPlanes; + buffer.put(1.toByte()) + buffer.put(0.toByte()) + //Int16 biBitCount; + buffer.put(32.toByte()) + buffer.put(0.toByte()) + //Compression + buffer.putInt(0) + //Int32 biSizeImage; + buffer.putInt(width * height * 4) + buffer.putInt(0) + buffer.putInt(0) + buffer.putInt(0) + buffer.putInt(0) + + //Image data + for (y in 0 until height) { + for (x in 0 until width) { + val argb: Int = this.getRGB(x, height - y - 1) + if (argb shr 24 and 0xFF == 0) { + buffer.putInt(0x00000000) + } else { + buffer.putInt(argb) + } + } + } + buffer.flip() + val hdrSizev5 = 0x7C + val bufferv5: ByteBuffer = ByteBuffer.allocate(hdrSizev5 + width * height * 4) + bufferv5.order(ByteOrder.LITTLE_ENDIAN) + //Header size + bufferv5.putInt(hdrSizev5) + //Width + bufferv5.putInt(width) + //Int32 biHeight; + bufferv5.putInt(height) + //Int16 biPlanes; + bufferv5.put(1.toByte()) + bufferv5.put(0.toByte()) + //Int16 biBitCount; + bufferv5.put(32.toByte()) + bufferv5.put(0.toByte()) + //Compression + bufferv5.putInt(0) + //Int32 biSizeImage; + bufferv5.putInt(width * height * 4) + bufferv5.putInt(0) + bufferv5.putInt(0) + bufferv5.putInt(0) + bufferv5.putInt(0) + bufferv5.order(ByteOrder.BIG_ENDIAN) + bufferv5.putInt(-0x1000000) + bufferv5.putInt(0x00FF0000) + bufferv5.putInt(0x0000FF00) + bufferv5.putInt(0x000000FF) + bufferv5.order(ByteOrder.LITTLE_ENDIAN) + + //BGRs + bufferv5.put(0x42.toByte()) + bufferv5.put(0x47.toByte()) + bufferv5.put(0x52.toByte()) + bufferv5.put(0x73.toByte()) + for (i in bufferv5.position() until hdrSizev5) { + bufferv5.put(0.toByte()) + } + + //Image data + for (y in 0 until height) { + for (x in 0 until width) { + val argb: Int = this.getRGB(x, height - y - 1) + val a = argb shr 24 and 0xFF + var r = argb shr 16 and 0xFF + var g = argb shr 8 and 0xFF + var b = argb and 0xFF + r = r * a / 0xFF + g = g * a / 0xFF + b = b * a / 0xFF + bufferv5.putInt(a shl 24 or (r shl 16) or (g shl 8) or b) + } + } + bufferv5.flip() + val clip = Toolkit.getDefaultToolkit().systemClipboard + val dt = DataTransferer.getInstance() + val f: Field = dt.javaClass.getDeclaredField("CF_DIB") + f.isAccessible = true + val format: Long = f.getLong(null) + val openClipboard: Method = clip.javaClass.getDeclaredMethod("openClipboard", SunClipboard::class.java) + openClipboard.isAccessible = true + openClipboard.invoke(clip, clip) + val publishClipboardData: Method = clip.javaClass.getDeclaredMethod( + "publishClipboardData", + Long::class.javaPrimitiveType, + ByteArray::class.java + ) + publishClipboardData.isAccessible = true + val arr: ByteArray = buffer.array() + publishClipboardData.invoke(clip, format, arr) + val closeClipboard: Method = clip.javaClass.getDeclaredMethod("closeClipboard") + closeClipboard.isAccessible = true + closeClipboard.invoke(clip) + return + } catch (e: Exception) { + e.printStackTrace() + } + } + val pixels: IntArray = + this.getRGB(0, 0, this.width, this.height, null, 0, this.width) + val newImage = BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB) + newImage.setRGB(0, 0, newImage.width, newImage.height, pixels, 0, newImage.width) + + try { + IOUtils.copyImageToClipboard(this) + } catch (e: Exception) { + e.printStackTrace() + } +} + +/** + * Taken from https://github.com/Moulberry/HyChat + */ +fun Framebuffer.screenshot(file: File): BufferedImage { + val w = this.framebufferWidth + val h = this.framebufferHeight + val i = w * h + val pixelBuffer = BufferUtils.createIntBuffer(i) + val pixelValues = IntArray(i) + GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1) + GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1) + GlStateManager.bindTexture(this.framebufferTexture) + GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixelBuffer) + pixelBuffer[pixelValues] //Load buffer into array + TextureUtil.processPixelValues(pixelValues, w, h) //Flip vertically + val bufferedimage = BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB) + val j = this.framebufferTextureHeight - this.framebufferHeight + for (k in j until this.framebufferTextureHeight) { + for (l in 0 until this.framebufferWidth) { + bufferedimage.setRGB(l, k - j, pixelValues[k * this.framebufferTextureWidth + l]) + } + } + if (ChattingConfig.copyMode != 1) { + try { + file.parentFile.mkdirs() + ImageIO.write(bufferedimage, "png", file) + } catch (e: Exception) { + e.printStackTrace() + } + } + return bufferedimage +} +/*/ +private val timePattern = Regex("\\[\\d+:\\d+:\\d+]") +private var lastLines = mutableListOf() +fun timestampPre() { + if (!ChattingConfig.showTimestampHover) return + val drawnChatLines = (Minecraft.getMinecraft().ingameGUI.chatGUI as GuiNewChatAccessor).drawnChatLines + val chatLine = getChatLineOverMouse(UMouse.getTrueX().roundToInt(), UMouse.getTrueY().roundToInt()) + + lastLines.clear() + for (line in drawnChatLines) { + val chatComponent = line.chatComponent.createCopy() + val newline = ChatLine(line.updatedCounter, chatComponent, line.chatLineID) + lastLines.add(newline) + } + + drawnChatLines.map { + if (it != chatLine) it.chatComponent.siblings.removeAll { itt -> + timePattern.find(ChatColor.stripControlCodes(itt.unformattedText)!!) != null + } + } +} + +fun timestampPost() { + if (!ChattingConfig.showTimestampHover) return + val drawnChatLines = (Minecraft.getMinecraft().ingameGUI.chatGUI as GuiNewChatAccessor).drawnChatLines + drawnChatLines.clear() + drawnChatLines.addAll(lastLines) +} + +private fun getChatLineOverMouse(mouseX: Int, mouseY: Int): ChatLine? { + val chat = Minecraft.getMinecraft().ingameGUI.chatGUI + if (!chat.chatOpen) return null + val scaledResolution = ScaledResolution(Minecraft.getMinecraft()) + val i = scaledResolution.scaleFactor + val f = chat.chatScale + val j = MathHelper.floor_float((mouseX / i - 3).toFloat() / f) + val k = MathHelper.floor_float((mouseY / i - 27).toFloat() / f) + if (j < 0 || k < 0) return null + val drawnChatLines = (chat as GuiNewChatAccessor).drawnChatLines + val l = chat.lineCount.coerceAtMost(drawnChatLines.size) + if (j <= MathHelper.floor_float(chat.chatWidth.toFloat() / f) && k < fontRenderer.FONT_HEIGHT * l + l) { + val m = k / Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT + chat.scrollPos + if (m >= 0 && m < drawnChatLines.size) + return drawnChatLines[m] + } + return null +} + + */ \ No newline at end of file -- cgit