From 2e2e3c2edc32dd526a39a5e9b5a62c524398fe19 Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Wed, 27 Dec 2023 21:19:29 -0500 Subject: [PATCH 01/13] Added screenshot functionality to client --- client/src/main/java/rt4/client.java | 65 ++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index fc98275..f1cca1a 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -1,14 +1,21 @@ package rt4; +import com.jogamp.opengl.GL2; +import com.jogamp.opengl.util.GLReadBufferUtil; import org.openrs2.deob.annotation.OriginalArg; import org.openrs2.deob.annotation.OriginalClass; import org.openrs2.deob.annotation.OriginalMember; import org.openrs2.deob.annotation.Pc; import plugin.PluginRepository; +import javax.imageio.ImageIO; import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; import java.io.IOException; import java.net.Socket; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; import java.util.Calendar; import java.util.GregorianCalendar; @@ -483,6 +490,64 @@ public final class client extends GameShell { } arg0.pdata(local15, 24); } + + public void saveScreenshot(String filename) { + int width = client.canvasWidth; + int height = client.canvasHeight; + if (GlRenderer.enabled) { + try { + GL2 gl = GlRenderer.gl; + // Create a buffer to hold the pixels + ByteBuffer buffer = ByteBuffer.allocateDirect(width * height * 4); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + // Read the pixels from the buffer + gl.glReadPixels(0, 0, width, height, GL2.GL_RGBA, GL2.GL_UNSIGNED_BYTE, buffer); + buffer.rewind(); + + // Create a BufferedImage and set its pixels + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + for (int h = 0; h < height; h++) { + for (int w = 0; w < width; w++) { + int b = buffer.get() & 0xFF; // Blue component + int g = buffer.get() & 0xFF; // Green component + int r = buffer.get() & 0xFF; // Red component + int a = buffer.get() & 0xFF; // Alpha component + int pixel = (a << 24) | (b << 16) | (g << 8) | r; + image.setRGB(w, height - h - 1, pixel); + } + } + + // Save the BufferedImage + File outputFile = new File(filename); + ImageIO.write(image, "png", outputFile); + System.out.println("Screenshot captured: " + filename); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + try { + Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow(); + Point point = window.getLocationOnScreen(); + int x = (int) point.getX(); + int y = (int) point.getY(); + int w = window.getWidth(); + int h = window.getHeight(); + Robot robot = new Robot(window.getGraphicsConfiguration().getDevice()); + Rectangle captureSize = new Rectangle(x, y, w, h); + BufferedImage image = robot.createScreenCapture(captureSize); + + // Save the BufferedImage + File outputFile = new File(filename); + ImageIO.write(image, "png", outputFile); + System.out.println("Screenshot captured: " + filename); + } catch (IOException e) { + e.printStackTrace(); + } catch (AWTException e) { + throw new RuntimeException(e); + } + } + } @OriginalMember(owner = "client!lb", name = "a", descriptor = "(Z)V") public static void method2721() { From 75e6a689257d4c2d84e90544b6ea3bf84b6401a1 Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Wed, 27 Dec 2023 21:25:28 -0500 Subject: [PATCH 02/13] Added screenshot functionality to API --- client/src/main/java/plugin/api/API.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/src/main/java/plugin/api/API.java b/client/src/main/java/plugin/api/API.java index 2f31ebc..3e34c5f 100644 --- a/client/src/main/java/plugin/api/API.java +++ b/client/src/main/java/plugin/api/API.java @@ -8,7 +8,9 @@ import rt4.Font; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import static rt4.MathUtils.clamp; import static rt4.Player.plane; @@ -270,6 +272,12 @@ public class API { public static void DispatchCommand(String command) { Cheat.sendCheatPacket(JagString.of(command)); } + + public static void Screenshot() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss"); + String dateTime = dateFormat.format(new Date()); + client.instance.saveScreenshot(PlayerList.self.username.toString() + "_" + dateTime + ".png"); + } public static void PlaySound(int volume, int trackId, int delay) { SoundPlayer.play(volume, trackId, delay); From dc8462dd55dddd3806e520234a87c7e01507feae Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Wed, 27 Dec 2023 21:30:53 -0500 Subject: [PATCH 03/13] Added take screenshot plugin --- .../src/main/kotlin/TakeScreenshot/plugin.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 plugin-playground/src/main/kotlin/TakeScreenshot/plugin.kt diff --git a/plugin-playground/src/main/kotlin/TakeScreenshot/plugin.kt b/plugin-playground/src/main/kotlin/TakeScreenshot/plugin.kt new file mode 100644 index 0000000..d250c18 --- /dev/null +++ b/plugin-playground/src/main/kotlin/TakeScreenshot/plugin.kt @@ -0,0 +1,24 @@ +package TakeScreenshot + +import plugin.Plugin +import plugin.annotations.PluginMeta +import plugin.api.API +import java.awt.event.KeyAdapter +import java.awt.event.KeyEvent + +@PluginMeta ( + author = "ipkpjersi", + description = "Allows you to use CRTL + PRINTSCREEN to take a screenshot.", + version = 1.0 +) +class plugin : Plugin() { + override fun Init() { + API.AddKeyboardListener(object : KeyAdapter() { + override fun keyPressed(e: KeyEvent) { + if (e.keyCode == KeyEvent.VK_PRINTSCREEN && e.isControlDown) { + API.Screenshot() + } + } + }) + } +} \ No newline at end of file From 4a5085380efcd2b2863e3f09aadad4e274d66c6e Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Thu, 28 Dec 2023 21:36:09 -0500 Subject: [PATCH 04/13] Use correct directory for screenshots --- client/src/main/java/rt4/client.java | 43 +++++++++++++++++-- .../src/main/kotlin/TakeScreenshot/plugin.kt | 2 +- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index f1cca1a..ff40855 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -492,6 +492,43 @@ public final class client extends GameShell { } public void saveScreenshot(String filename) { + String homeDirOverride = System.getProperty("clientHomeOverride"); + String homeDir = null; + String osNameRaw = ""; + String osName = ""; + try { + osNameRaw = System.getProperty("os.name"); + } catch (Exception local48) { + osNameRaw = "Unknown"; + } + osName = osNameRaw.toLowerCase(); + if (homeDirOverride != null) { + homeDir = homeDirOverride; + } else { + try { + if (homeDir == null) + homeDir = System.getProperty("user.home") + File.separatorChar; + + if (osName.startsWith("linux")) { + String xdgHome = System.getenv("XDG_DATA_HOME"); + + if (xdgHome != null) { + homeDir = xdgHome + "/2009scape/"; + } else { + homeDir += ".local/share/2009scape/"; + } + } else if (osName.startsWith("mac")) { + homeDir += "Library/Application Support/2009scape/"; + } else if (osName.startsWith("windows")) { + homeDir += "2009scape\\"; + } + } catch (Exception ex) { + } + } + File outputFolder = new File(homeDir + File.separatorChar + "screenshots" + File.separatorChar); + if (!outputFolder.exists()){ + outputFolder.mkdirs(); + } int width = client.canvasWidth; int height = client.canvasHeight; if (GlRenderer.enabled) { @@ -519,9 +556,8 @@ public final class client extends GameShell { } // Save the BufferedImage - File outputFile = new File(filename); + File outputFile = new File(outputFolder, filename); ImageIO.write(image, "png", outputFile); - System.out.println("Screenshot captured: " + filename); } catch (IOException e) { e.printStackTrace(); } @@ -538,9 +574,8 @@ public final class client extends GameShell { BufferedImage image = robot.createScreenCapture(captureSize); // Save the BufferedImage - File outputFile = new File(filename); + File outputFile = new File(outputFolder, filename); ImageIO.write(image, "png", outputFile); - System.out.println("Screenshot captured: " + filename); } catch (IOException e) { e.printStackTrace(); } catch (AWTException e) { diff --git a/plugin-playground/src/main/kotlin/TakeScreenshot/plugin.kt b/plugin-playground/src/main/kotlin/TakeScreenshot/plugin.kt index d250c18..174200a 100644 --- a/plugin-playground/src/main/kotlin/TakeScreenshot/plugin.kt +++ b/plugin-playground/src/main/kotlin/TakeScreenshot/plugin.kt @@ -17,7 +17,7 @@ class plugin : Plugin() { override fun keyPressed(e: KeyEvent) { if (e.keyCode == KeyEvent.VK_PRINTSCREEN && e.isControlDown) { API.Screenshot() - } + } } }) } From 6d2d8ad36d6619723fcba7c4dba14f4ef01ead6e Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Fri, 29 Dec 2023 12:45:24 -0500 Subject: [PATCH 05/13] Added subfolders option This allows for much greater flexibility of screenshotting, we can now pass in any number of levels of subfolders for our preferred directory depth for storing images. --- client/src/main/java/plugin/api/API.java | 4 ++-- client/src/main/java/rt4/client.java | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/client/src/main/java/plugin/api/API.java b/client/src/main/java/plugin/api/API.java index 3e34c5f..d84d27e 100644 --- a/client/src/main/java/plugin/api/API.java +++ b/client/src/main/java/plugin/api/API.java @@ -273,10 +273,10 @@ public class API { Cheat.sendCheatPacket(JagString.of(command)); } - public static void Screenshot() { + public static void Screenshot(String... subfolders) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss"); String dateTime = dateFormat.format(new Date()); - client.instance.saveScreenshot(PlayerList.self.username.toString() + "_" + dateTime + ".png"); + client.instance.saveScreenshot(PlayerList.self.username.toString() + "_" + dateTime + ".png", subfolders); } public static void PlaySound(int volume, int trackId, int delay) { diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index ff40855..3ce80e8 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -491,7 +491,7 @@ public final class client extends GameShell { arg0.pdata(local15, 24); } - public void saveScreenshot(String filename) { + public void saveScreenshot(String filename, String... subfolders) { String homeDirOverride = System.getProperty("clientHomeOverride"); String homeDir = null; String osNameRaw = ""; @@ -525,7 +525,13 @@ public final class client extends GameShell { } catch (Exception ex) { } } - File outputFolder = new File(homeDir + File.separatorChar + "screenshots" + File.separatorChar); + + String subfolderPath = String.join(File.separator, subfolders); + if (!subfolderPath.isEmpty()) { + subfolderPath += File.separator; + } + + File outputFolder = new File(homeDir + File.separatorChar + "screenshots" + File.separatorChar + subfolderPath); if (!outputFolder.exists()){ outputFolder.mkdirs(); } From ec65b9e947cb3c86329727446cb8d28f0ee9df1e Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Sat, 30 Dec 2023 22:33:57 -0500 Subject: [PATCH 06/13] Fixed formatting --- client/src/main/java/rt4/client.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index 3ce80e8..3d8c339 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -504,7 +504,7 @@ public final class client extends GameShell { osName = osNameRaw.toLowerCase(); if (homeDirOverride != null) { homeDir = homeDirOverride; - } else { + } else { try { if (homeDir == null) homeDir = System.getProperty("user.home") + File.separatorChar; @@ -585,9 +585,9 @@ public final class client extends GameShell { } catch (IOException e) { e.printStackTrace(); } catch (AWTException e) { - throw new RuntimeException(e); - } - } + throw new RuntimeException(e); + } + } } @OriginalMember(owner = "client!lb", name = "a", descriptor = "(Z)V") From 40b1fc47a6beaa40569dd0832c4dae8494fe3ec3 Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Sat, 30 Dec 2023 22:45:13 -0500 Subject: [PATCH 07/13] Simplified the screenshot capturing We don't actually need to capture the OpenGL buffer itself, this is fine. Also it simplifies the code a fair bit too, and as an added benefit we can also capture the entire window including the border/decorations etc. --- client/src/main/java/rt4/client.java | 46 +++++----------------------- 1 file changed, 7 insertions(+), 39 deletions(-) diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index 3d8c339..d124a93 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -535,40 +535,8 @@ public final class client extends GameShell { if (!outputFolder.exists()){ outputFolder.mkdirs(); } - int width = client.canvasWidth; - int height = client.canvasHeight; - if (GlRenderer.enabled) { - try { - GL2 gl = GlRenderer.gl; - // Create a buffer to hold the pixels - ByteBuffer buffer = ByteBuffer.allocateDirect(width * height * 4); - buffer.order(ByteOrder.LITTLE_ENDIAN); - - // Read the pixels from the buffer - gl.glReadPixels(0, 0, width, height, GL2.GL_RGBA, GL2.GL_UNSIGNED_BYTE, buffer); - buffer.rewind(); - - // Create a BufferedImage and set its pixels - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - for (int h = 0; h < height; h++) { - for (int w = 0; w < width; w++) { - int b = buffer.get() & 0xFF; // Blue component - int g = buffer.get() & 0xFF; // Green component - int r = buffer.get() & 0xFF; // Red component - int a = buffer.get() & 0xFF; // Alpha component - int pixel = (a << 24) | (b << 16) | (g << 8) | r; - image.setRGB(w, height - h - 1, pixel); - } - } - - // Save the BufferedImage - File outputFile = new File(outputFolder, filename); - ImageIO.write(image, "png", outputFile); - } catch (IOException e) { - e.printStackTrace(); - } - } else { - try { + + try { Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow(); Point point = window.getLocationOnScreen(); int x = (int) point.getX(); @@ -582,12 +550,12 @@ public final class client extends GameShell { // Save the BufferedImage File outputFile = new File(outputFolder, filename); ImageIO.write(image, "png", outputFile); - } catch (IOException e) { - e.printStackTrace(); - } catch (AWTException e) { - throw new RuntimeException(e); - } + } catch (IOException e) { + e.printStackTrace(); + } catch (AWTException e) { + throw new RuntimeException(e); } + } @OriginalMember(owner = "client!lb", name = "a", descriptor = "(Z)V") From d52be460c69a8a3e4ec44d1b818d4a91769b9f4d Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Sat, 6 Jan 2024 16:10:51 -0500 Subject: [PATCH 08/13] Added check for screenshots --- client/src/main/java/rt4/client.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index d124a93..c4b2ac7 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -538,6 +538,9 @@ public final class client extends GameShell { try { Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow(); + if (window == null) { + return; + } Point point = window.getLocationOnScreen(); int x = (int) point.getX(); int y = (int) point.getY(); From 3762aed1338ce6343276f54d26fc63fe4be73bee Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Sat, 6 Jan 2024 16:11:34 -0500 Subject: [PATCH 09/13] Cleaned up screenshot code --- client/src/main/java/rt4/client.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index c4b2ac7..f81d97d 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -549,8 +549,6 @@ public final class client extends GameShell { Robot robot = new Robot(window.getGraphicsConfiguration().getDevice()); Rectangle captureSize = new Rectangle(x, y, w, h); BufferedImage image = robot.createScreenCapture(captureSize); - - // Save the BufferedImage File outputFile = new File(outputFolder, filename); ImageIO.write(image, "png", outputFile); } catch (IOException e) { From 2079ec7459e3b83b65ed72b13dd8bc9757b5f531 Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Sat, 6 Jan 2024 16:12:04 -0500 Subject: [PATCH 10/13] Catch all exceptions for screenshots This makes the code more reliable. --- client/src/main/java/rt4/client.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index f81d97d..1fc020d 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -551,11 +551,11 @@ public final class client extends GameShell { BufferedImage image = robot.createScreenCapture(captureSize); File outputFile = new File(outputFolder, filename); ImageIO.write(image, "png", outputFile); - } catch (IOException e) { - e.printStackTrace(); } catch (AWTException e) { throw new RuntimeException(e); - } + } catch (Exception e) { + e.printStackTrace(); + } } From 008324aa8422e659563106c7e5ca6c9b25fe672a Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Sat, 6 Jan 2024 16:12:29 -0500 Subject: [PATCH 11/13] Removed extra whitespace --- client/src/main/java/rt4/client.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index 1fc020d..292785a 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -555,8 +555,7 @@ public final class client extends GameShell { throw new RuntimeException(e); } catch (Exception e) { e.printStackTrace(); - } - + } } @OriginalMember(owner = "client!lb", name = "a", descriptor = "(Z)V") From 328e24e243c88ce70804692de7358c72a34dce37 Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Sat, 6 Jan 2024 16:13:18 -0500 Subject: [PATCH 12/13] Removed specific AWT catch It's better if we handle it here instead of bubbling the exception up the stack. --- client/src/main/java/rt4/client.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index 292785a..5ddd87e 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -551,8 +551,6 @@ public final class client extends GameShell { BufferedImage image = robot.createScreenCapture(captureSize); File outputFile = new File(outputFolder, filename); ImageIO.write(image, "png", outputFile); - } catch (AWTException e) { - throw new RuntimeException(e); } catch (Exception e) { e.printStackTrace(); } From 70c3455df8527475c6b855ee6f49ba7725d90a07 Mon Sep 17 00:00:00 2001 From: ipkpjersi Date: Mon, 8 Jan 2024 19:10:51 -0500 Subject: [PATCH 13/13] Fixed screenshot NPE when not logged in --- client/src/main/java/plugin/api/API.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/plugin/api/API.java b/client/src/main/java/plugin/api/API.java index d84d27e..b545280 100644 --- a/client/src/main/java/plugin/api/API.java +++ b/client/src/main/java/plugin/api/API.java @@ -276,7 +276,8 @@ public class API { public static void Screenshot(String... subfolders) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss"); String dateTime = dateFormat.format(new Date()); - client.instance.saveScreenshot(PlayerList.self.username.toString() + "_" + dateTime + ".png", subfolders); + String username = PlayerList.self != null && PlayerList.self.username != null && !PlayerList.self.username.toString().isEmpty() ? PlayerList.self.username.toString() : "2009Scape"; + client.instance.saveScreenshot( username + "_" + dateTime + ".png", subfolders); } public static void PlaySound(int volume, int trackId, int delay) {