From 668345b81e1713a21e1f0a29bbe6fbcfe228624c Mon Sep 17 00:00:00 2001 From: downthecrop Date: Thu, 24 Oct 2024 12:03:16 -0700 Subject: [PATCH 01/25] FIXED streched mode --- client/src/main/java/plugin/Plugin.java | 15 ++ .../main/java/plugin/PluginRepository.java | 5 + client/src/main/java/rt4/FrameBuffer.java | 2 +- client/src/main/java/rt4/client.java | 1 + .../src/main/kotlin/KondoKit/plugin.kt | 176 +++++++++++++++++- 5 files changed, 191 insertions(+), 8 deletions(-) diff --git a/client/src/main/java/plugin/Plugin.java b/client/src/main/java/plugin/Plugin.java index 7a4a039..e8e3641 100644 --- a/client/src/main/java/plugin/Plugin.java +++ b/client/src/main/java/plugin/Plugin.java @@ -13,6 +13,7 @@ import rt4.Tile; */ public abstract class Plugin { long timeOfLastDraw; + long timeOfLastLateDraw; void _init() { Init(); @@ -24,6 +25,12 @@ public abstract class Plugin { timeOfLastDraw = nowTime; } + void _lateDraw() { + long nowTime = System.currentTimeMillis(); + LateDraw(nowTime - timeOfLastLateDraw); + timeOfLastLateDraw = nowTime; + } + /** * Draw() is called by the client rendering loop so that plugins can draw information onto the screen. * This will be called once per frame, meaning it is framerate bound. @@ -31,6 +38,14 @@ public abstract class Plugin { */ public void Draw(long timeDelta) {} + + /** + * LateDraw() is called at the end of a finalized frame + * This will be called once per frame, meaning it is framerate bound. + * @param timeDelta the time (ms) elapsed since the last draw call. + */ + public void LateDraw(long timeDelta) {} + /** * Init() is called when the plugin is first loaded */ diff --git a/client/src/main/java/plugin/PluginRepository.java b/client/src/main/java/plugin/PluginRepository.java index 2af27f6..55faf80 100644 --- a/client/src/main/java/plugin/PluginRepository.java +++ b/client/src/main/java/plugin/PluginRepository.java @@ -160,6 +160,11 @@ public class PluginRepository { pluginsSnapshot.forEach(Plugin::_draw); } + public static void LateDraw() { + List pluginsSnapshot = new ArrayList<>(loadedPlugins.values()); + pluginsSnapshot.forEach(Plugin::_lateDraw); + } + public static void NPCOverheadDraw(Npc npc, int screenX, int screenY) { loadedPlugins.values().forEach((plugin) -> plugin.NPCOverheadDraw(npc, screenX, screenY)); } diff --git a/client/src/main/java/rt4/FrameBuffer.java b/client/src/main/java/rt4/FrameBuffer.java index 5999c44..f641434 100644 --- a/client/src/main/java/rt4/FrameBuffer.java +++ b/client/src/main/java/rt4/FrameBuffer.java @@ -12,7 +12,7 @@ import java.awt.*; public abstract class FrameBuffer { @OriginalMember(owner = "client!vk", name = "e", descriptor = "[I") - protected int[] pixels; + public int[] pixels; @OriginalMember(owner = "client!vk", name = "g", descriptor = "Ljava/awt/Image;") protected Image image; diff --git a/client/src/main/java/rt4/client.java b/client/src/main/java/rt4/client.java index 34adc87..7a77445 100644 --- a/client/src/main/java/rt4/client.java +++ b/client/src/main/java/rt4/client.java @@ -921,6 +921,7 @@ public final class client extends GameShell { Preferences.safeMode = false; Preferences.write(GameShell.signLink); } + PluginRepository.LateDraw(); } @OriginalMember(owner = "client!client", name = "c", descriptor = "(B)V") diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index bc0f6b3..f4a604f 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -35,16 +35,17 @@ import plugin.api.* import plugin.api.API.* import plugin.api.FontColor.fromColor import rt4.GameShell +import rt4.GameShell.canvas import rt4.GameShell.frame import rt4.GlRenderer import rt4.InterfaceList import rt4.Player +import rt4.SoftwareRaster import rt4.client.js5Archive8 import rt4.client.mainLoadState import java.awt.* -import java.awt.event.ActionListener -import java.awt.event.MouseAdapter -import java.awt.event.MouseEvent +import java.awt.event.* +import java.awt.image.BufferedImage import javax.swing.* import javax.swing.plaf.nimbus.AbstractRegionPainter @@ -149,12 +150,157 @@ class plugin : Plugin() { } lastLogin = Player.usernameInput.toString() } + class AltCanvas(private val mainCanvas: Canvas) : JPanel() { + private var gameImage: BufferedImage? = null + private var scaleX = 1.0 + private var scaleY = 1.0 + private var offsetX = 0 + private var offsetY = 0 + init { + gameImage = BufferedImage(765, 503, BufferedImage.TYPE_INT_ARGB) + val g = gameImage!!.createGraphics() + g.color = Color.RED + g.fillRect(0, 0, gameImage!!.width, gameImage!!.height) + g.color = Color.BLACK + g.drawString("Game Frame", 20, 20) + g.dispose() + + addMouseListener(object : MouseAdapter() { + override fun mousePressed(e: MouseEvent) { + relayMouseEvent(e) + } + + override fun mouseReleased(e: MouseEvent) { + relayMouseEvent(e) + } + + override fun mouseClicked(e: MouseEvent) { + relayMouseEvent(e) + } + }) + + addMouseMotionListener(object : MouseMotionAdapter() { + override fun mouseMoved(e: MouseEvent) { + relayMouseEvent(e) + } + + override fun mouseDragged(e: MouseEvent) { + relayMouseEvent(e) + } + }) + + // Register a KeyAdapter for handling key events + addKeyListener(object : KeyAdapter() { + override fun keyPressed(e: KeyEvent) { + for(listener in canvas.keyListeners){ + listener.keyPressed(e) + } + } + + override fun keyReleased(e: KeyEvent) { + for(listener in canvas.keyListeners){ + listener.keyReleased(e) + } + } + + override fun keyTyped(e: KeyEvent) { + for(listener in canvas.keyListeners){ + listener.keyTyped(e) + } + } + }) + + isFocusable = true + requestFocusInWindow() + } + + override fun paintComponent(g: Graphics) { + super.paintComponent(g) + val g2d = g as Graphics2D + + // Set the desired background fill color here + g2d.color = Color(30, 30, 30) // Replace with your preferred fill color + g2d.fillRect(0, 0, width, height) + gameImage?.let { image -> + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR) + + // Calculate aspect-ratio-preserving scale + val imageAspect = image.width.toDouble() / image.height.toDouble() + val panelAspect = width.toDouble() / height.toDouble() + + val (drawWidth, drawHeight) = if (imageAspect > panelAspect) { + val newWidth = width + val newHeight = (width / imageAspect).toInt() + newWidth to newHeight + } else { + val newHeight = height + val newWidth = (height * imageAspect).toInt() + newWidth to newHeight + } + + // Store scale factors and offsets for event adjustment + scaleX = drawWidth.toDouble() / image.width + scaleY = drawHeight.toDouble() / image.height + offsetX = (width - drawWidth) / 2 + offsetY = (height - drawHeight) / 2 + + // Draw the scaled image centered in the panel + val x = offsetX + val y = offsetY + g2d.drawImage(image, x, y, drawWidth, drawHeight, null) + } + } + + private fun relayMouseEvent(e: MouseEvent) { + val adjustedX = (e.x - offsetX) / scaleX + val adjustedY = (e.y - offsetY) / scaleY + + val originalX = adjustedX.toInt().coerceIn(0, gameImage!!.width - 1) + val originalY = adjustedY.toInt().coerceIn(0, gameImage!!.height - 1) + + val newEvent = MouseEvent( + mainCanvas, e.id, e.`when`, e.modifiersEx, + originalX, originalY, e.clickCount, e.isPopupTrigger, e.button + ) + + mainCanvas.dispatchEvent(newEvent) + } + + fun updateGameImage(newImage: BufferedImage) { + gameImage = newImage + repaint() + } + } + + + + fun createAltCanvas(mainCanvas: Canvas): AltCanvas { + return AltCanvas(mainCanvas).apply { + preferredSize = Dimension(FIXED_WIDTH, 503) + } + } + + private var altCanvas: AltCanvas? = null override fun Init() { // Disable Font AA System.setProperty("sun.java2d.opengl", "false") System.setProperty("awt.useSystemAAFontSettings", "off") System.setProperty("swing.aatext", "false") + val frame: Frame? = GameShell.frame + if (frame != null) { + // Create the AltCanvas and add it to the main frame + altCanvas = createAltCanvas(canvas) + + // Use BorderLayout for better layout control + frame.layout = BorderLayout() + + // Add the AltCanvas in the center to ensure it scales properly with the window size + frame.add(altCanvas, BorderLayout.NORTH) + frame.remove(canvas) + //frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE + frame.isVisible = true + } } private fun UpdateDisplaySettings() { @@ -166,9 +312,8 @@ class plugin : Plugin() { if (frame.width < FIXED_WIDTH + currentScrollPaneWidth + uiOffset) { frame.setSize(FIXED_WIDTH + currentScrollPaneWidth + uiOffset, frame.height) } - - val difference = frame.width - (FIXED_WIDTH + uiOffset + currentScrollPaneWidth) - GameShell.leftMargin = difference / 2 + val difference = frame.width - (uiOffset + currentScrollPaneWidth) + altCanvas?.size = Dimension(difference, frame.height - 30) } WindowMode.RESIZABLE -> { GameShell.canvasWidth = frame.width - (currentScrollPaneWidth + uiOffset) @@ -274,7 +419,7 @@ class plugin : Plugin() { } } - override fun Draw(timeDelta: Long) { + override fun LateDraw(timeDelta: Long) { if (GlRenderer.enabled && GlRenderer.canvasWidth != GameShell.canvasWidth) { GlRenderer.canvasWidth = GameShell.canvasWidth GlRenderer.setViewportBounds(0, 0, GameShell.canvasWidth, GameShell.canvasHeight) @@ -296,6 +441,10 @@ class plugin : Plugin() { accumulatedTime = 0L } + // Update game image here + val rasterImage = getRasterImageFromGameShell() // Replace this with the actual method to fetch the BufferedImage from GameShell.canvas. + altCanvas?.updateGameImage(rasterImage) + // Draw synced actions (that require to be done between glBegin and glEnd) if (drawActions.isNotEmpty()) { synchronized(drawActions) { @@ -313,6 +462,18 @@ class plugin : Plugin() { } } + // Placeholder method to get the game image from GameShell + fun getRasterImageFromGameShell(): BufferedImage { + // Assuming SoftwareRaster.pixels is an IntArray containing ARGB values of the game image. + val gameImage = BufferedImage(765, 503, BufferedImage.TYPE_INT_ARGB) + + val g = gameImage.createGraphics() + + SoftwareRaster.frameBuffer.draw(g) + return gameImage + } + + private fun initKondoUI(){ DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2) if(!allSpritesLoaded()) return; @@ -379,6 +540,7 @@ class plugin : Plugin() { // Update component tree UI to apply the new theme SwingUtilities.updateComponentTreeUI(GameShell.frame) + GameShell.frame.background = Color.BLACK } catch (e : Exception) { e.printStackTrace() } From 8e554b573c7d604871e344513124d21864cad731 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Thu, 24 Oct 2024 20:24:40 -0700 Subject: [PATCH 02/25] gather functions together for easier debugging --- .../src/main/kotlin/KondoKit/plugin.kt | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index f4a604f..5a6526c 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -220,7 +220,7 @@ class plugin : Plugin() { val g2d = g as Graphics2D // Set the desired background fill color here - g2d.color = Color(30, 30, 30) // Replace with your preferred fill color + g2d.color = Color.BLACK g2d.fillRect(0, 0, width, height) gameImage?.let { image -> g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR) @@ -273,15 +273,25 @@ class plugin : Plugin() { } } - - fun createAltCanvas(mainCanvas: Canvas): AltCanvas { return AltCanvas(mainCanvas).apply { preferredSize = Dimension(FIXED_WIDTH, 503) } } + fun getRasterImageFromGameShell(): BufferedImage { + // Assuming SoftwareRaster.pixels is an IntArray containing ARGB values of the game image. + val gameImage = BufferedImage(765, 503, BufferedImage.TYPE_INT_ARGB) + + val g = gameImage.createGraphics() + + SoftwareRaster.frameBuffer.draw(g) + return gameImage + } + private var altCanvas: AltCanvas? = null + + override fun Init() { // Disable Font AA System.setProperty("sun.java2d.opengl", "false") @@ -296,10 +306,8 @@ class plugin : Plugin() { frame.layout = BorderLayout() // Add the AltCanvas in the center to ensure it scales properly with the window size - frame.add(altCanvas, BorderLayout.NORTH) + altCanvas?.let { frame.add(it, BorderLayout.NORTH) } frame.remove(canvas) - //frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE - frame.isVisible = true } } @@ -442,7 +450,7 @@ class plugin : Plugin() { } // Update game image here - val rasterImage = getRasterImageFromGameShell() // Replace this with the actual method to fetch the BufferedImage from GameShell.canvas. + val rasterImage = getRasterImageFromGameShell() altCanvas?.updateGameImage(rasterImage) // Draw synced actions (that require to be done between glBegin and glEnd) @@ -462,18 +470,6 @@ class plugin : Plugin() { } } - // Placeholder method to get the game image from GameShell - fun getRasterImageFromGameShell(): BufferedImage { - // Assuming SoftwareRaster.pixels is an IntArray containing ARGB values of the game image. - val gameImage = BufferedImage(765, 503, BufferedImage.TYPE_INT_ARGB) - - val g = gameImage.createGraphics() - - SoftwareRaster.frameBuffer.draw(g) - return gameImage - } - - private fun initKondoUI(){ DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2) if(!allSpritesLoaded()) return; From af4dafee893bfe8fd621b3ce067271b66a83f491 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Thu, 24 Oct 2024 20:50:56 -0700 Subject: [PATCH 03/25] Convert to volatile and centralize logic to the altcanvas. --- .../src/main/kotlin/KondoKit/plugin.kt | 84 ++++++++++++------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 5a6526c..bc550e3 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -45,7 +45,7 @@ import rt4.client.js5Archive8 import rt4.client.mainLoadState import java.awt.* import java.awt.event.* -import java.awt.image.BufferedImage +import java.awt.image.VolatileImage import javax.swing.* import javax.swing.plaf.nimbus.AbstractRegionPainter @@ -151,20 +151,15 @@ class plugin : Plugin() { lastLogin = Player.usernameInput.toString() } class AltCanvas(private val mainCanvas: Canvas) : JPanel() { - private var gameImage: BufferedImage? = null + private var gameImage: VolatileImage? = null private var scaleX = 1.0 private var scaleY = 1.0 private var offsetX = 0 private var offsetY = 0 + init { - gameImage = BufferedImage(765, 503, BufferedImage.TYPE_INT_ARGB) - val g = gameImage!!.createGraphics() - g.color = Color.RED - g.fillRect(0, 0, gameImage!!.width, gameImage!!.height) - g.color = Color.BLACK - g.drawString("Game Frame", 20, 20) - g.dispose() + validateGameImage() addMouseListener(object : MouseAdapter() { override fun mousePressed(e: MouseEvent) { @@ -193,26 +188,55 @@ class plugin : Plugin() { // Register a KeyAdapter for handling key events addKeyListener(object : KeyAdapter() { override fun keyPressed(e: KeyEvent) { - for(listener in canvas.keyListeners){ + for (listener in mainCanvas.keyListeners) { listener.keyPressed(e) } } override fun keyReleased(e: KeyEvent) { - for(listener in canvas.keyListeners){ + for (listener in mainCanvas.keyListeners) { listener.keyReleased(e) } } override fun keyTyped(e: KeyEvent) { - for(listener in canvas.keyListeners){ + for (listener in mainCanvas.keyListeners) { listener.keyTyped(e) } } }) isFocusable = true - requestFocusInWindow() + } + + private fun validateGameImage() { + val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration + if (gameImage == null) { + gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.TRANSLUCENT) + renderGameImage() + } else { + val status = gameImage!!.validate(gc) + if (status == VolatileImage.IMAGE_INCOMPATIBLE) { + gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.TRANSLUCENT) + renderGameImage() + } else if (status == VolatileImage.IMAGE_RESTORED) { + renderGameImage() + } + } + } + + private fun renderGameImage() { + val g = gameImage!!.createGraphics() + try { + // Initial drawing code + g.color = Color.RED + g.fillRect(0, 0, gameImage!!.width, gameImage!!.height) + g.color = Color.BLACK + g.drawString("Game Frame", 20, 20) + // Add any additional rendering here + } finally { + g.dispose() + } } override fun paintComponent(g: Graphics) { @@ -222,6 +246,9 @@ class plugin : Plugin() { // Set the desired background fill color here g2d.color = Color.BLACK g2d.fillRect(0, 0, width, height) + + validateGameImage() + gameImage?.let { image -> g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR) @@ -267,8 +294,14 @@ class plugin : Plugin() { mainCanvas.dispatchEvent(newEvent) } - fun updateGameImage(newImage: BufferedImage) { - gameImage = newImage + fun updateGameImage() { + validateGameImage() + val g = gameImage!!.createGraphics() + try { + SoftwareRaster.frameBuffer.draw(g) + } finally { + g.dispose() + } repaint() } } @@ -279,16 +312,6 @@ class plugin : Plugin() { } } - fun getRasterImageFromGameShell(): BufferedImage { - // Assuming SoftwareRaster.pixels is an IntArray containing ARGB values of the game image. - val gameImage = BufferedImage(765, 503, BufferedImage.TYPE_INT_ARGB) - - val g = gameImage.createGraphics() - - SoftwareRaster.frameBuffer.draw(g) - return gameImage - } - private var altCanvas: AltCanvas? = null @@ -427,7 +450,7 @@ class plugin : Plugin() { } } - override fun LateDraw(timeDelta: Long) { + override fun Draw(timeDelta: Long) { if (GlRenderer.enabled && GlRenderer.canvasWidth != GameShell.canvasWidth) { GlRenderer.canvasWidth = GameShell.canvasWidth GlRenderer.setViewportBounds(0, 0, GameShell.canvasWidth, GameShell.canvasHeight) @@ -449,10 +472,6 @@ class plugin : Plugin() { accumulatedTime = 0L } - // Update game image here - val rasterImage = getRasterImageFromGameShell() - altCanvas?.updateGameImage(rasterImage) - // Draw synced actions (that require to be done between glBegin and glEnd) if (drawActions.isNotEmpty()) { synchronized(drawActions) { @@ -470,6 +489,11 @@ class plugin : Plugin() { } } + override fun LateDraw(timeDelta: Long){ + // Update game image here + altCanvas?.updateGameImage() + } + private fun initKondoUI(){ DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2) if(!allSpritesLoaded()) return; From 1eb7483d3561dd80d3623c32d37e0ba7b2138ccd Mon Sep 17 00:00:00 2001 From: downthecrop Date: Thu, 24 Oct 2024 20:58:45 -0700 Subject: [PATCH 04/25] Regain focus on click --- plugin-playground/src/main/kotlin/KondoKit/plugin.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index bc550e3..a1b5137 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -41,13 +41,11 @@ import rt4.GlRenderer import rt4.InterfaceList import rt4.Player import rt4.SoftwareRaster -import rt4.client.js5Archive8 -import rt4.client.mainLoadState +import rt4.client.* import java.awt.* import java.awt.event.* import java.awt.image.VolatileImage import javax.swing.* -import javax.swing.plaf.nimbus.AbstractRegionPainter @Target(AnnotationTarget.FIELD) @@ -207,6 +205,7 @@ class plugin : Plugin() { }) isFocusable = true + requestFocusInWindow() } private fun validateGameImage() { @@ -280,6 +279,7 @@ class plugin : Plugin() { } private fun relayMouseEvent(e: MouseEvent) { + this.requestFocusInWindow() val adjustedX = (e.x - offsetX) / scaleX val adjustedY = (e.y - offsetY) / scaleY From 838acc57ff5cd447f35012083fb57df2ba90f646 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Thu, 24 Oct 2024 23:21:55 -0700 Subject: [PATCH 05/25] handing for altcanvas in alerts --- plugin-playground/src/main/kotlin/KondoKit/Helpers.kt | 2 +- plugin-playground/src/main/kotlin/KondoKit/plugin.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/Helpers.kt b/plugin-playground/src/main/kotlin/KondoKit/Helpers.kt index bfcac22..67530e3 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/Helpers.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/Helpers.kt @@ -68,7 +68,7 @@ object Helpers { // Adjust for parent component location if it exists - if (parentComponent != null) { + if (parentComponent != null && GameShell.canvas.isShowing) { val parentLocation = parentComponent.locationOnScreen val x = parentLocation.x val y = GameShell.canvas.locationOnScreen.y diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index a1b5137..6e1adbb 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -324,7 +324,7 @@ class plugin : Plugin() { if (frame != null) { // Create the AltCanvas and add it to the main frame altCanvas = createAltCanvas(canvas) - + canvas.isVisible = false // Use BorderLayout for better layout control frame.layout = BorderLayout() From b3c2adc51f1c4af2a93269f5a6c2eadc5b1951fa Mon Sep 17 00:00:00 2001 From: downthecrop Date: Fri, 25 Oct 2024 15:54:39 -0700 Subject: [PATCH 06/25] support scaled fixed HD --- client/src/main/java/rt4/DisplayMode.java | 6 ++ client/src/main/java/rt4/GameShell.java | 1 + client/src/main/java/rt4/GlRenderer.java | 15 +++- .../src/main/kotlin/KondoKit/plugin.kt | 87 +++++++++++++++---- 4 files changed, 88 insertions(+), 21 deletions(-) diff --git a/client/src/main/java/rt4/DisplayMode.java b/client/src/main/java/rt4/DisplayMode.java index 440e79d..58bf779 100644 --- a/client/src/main/java/rt4/DisplayMode.java +++ b/client/src/main/java/rt4/DisplayMode.java @@ -79,6 +79,12 @@ public final class DisplayMode { @OriginalMember(owner = "client!pm", name = "a", descriptor = "(ZIZIZII)V") public static void setWindowMode(@OriginalArg(0) boolean replaceCanvas, @OriginalArg(1) int newMode, @OriginalArg(2) boolean useHD, @OriginalArg(3) int currentMode, @OriginalArg(5) int width, @OriginalArg(6) int height) { + if(!GameShell.canvas.isShowing()){ + GameShell.frame.add(GameShell.canvas); + GameShell.canvas.revalidate(); + GameShell.frame.revalidate(); + GameShell.canvas.repaint(); + } if (useHD) { GlRenderer.quit(); } diff --git a/client/src/main/java/rt4/GameShell.java b/client/src/main/java/rt4/GameShell.java index 80a799d..9bd0bd6 100644 --- a/client/src/main/java/rt4/GameShell.java +++ b/client/src/main/java/rt4/GameShell.java @@ -323,6 +323,7 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene @OriginalMember(owner = "client!rc", name = "b", descriptor = "(B)V") public final synchronized void addCanvas() { if (canvas != null) { + // Remove the old canvas if it exists canvas.removeFocusListener(this); canvas.getParent().remove(canvas); } diff --git a/client/src/main/java/rt4/GlRenderer.java b/client/src/main/java/rt4/GlRenderer.java index b42e0de..c7a7d2a 100644 --- a/client/src/main/java/rt4/GlRenderer.java +++ b/client/src/main/java/rt4/GlRenderer.java @@ -24,6 +24,8 @@ public final class GlRenderer { public static float hFOV = 0; + public static int[] pixelData = null; + @OriginalMember(owner = "client!tf", name = "c", descriptor = "F") private static float aFloat30; @@ -67,7 +69,7 @@ public final class GlRenderer { private static int maxTextureCoords; @OriginalMember(owner = "client!tf", name = "E", descriptor = "Lgl!javax/media/opengl/GLDrawable;") - private static GLDrawable drawable; + public static GLDrawable drawable; @OriginalMember(owner = "client!tf", name = "H", descriptor = "Z") public static boolean arbVertexProgramSupported; @@ -199,11 +201,20 @@ public final class GlRenderer { @OriginalMember(owner = "client!tf", name = "d", descriptor = "()V") public static void swapBuffers() { try { + pixelData = readPixels(); drawable.swapBuffers(); - } catch (@Pc(3) Exception local3) { + } catch (@Pc(3) Exception local3) {*, } } + @OriginalMember(owner = "client!tf", name = "readPixels", descriptor = "()int[]") + public static int[] readPixels() { + int[] pixels = new int[canvasWidth * canvasHeight]; + IntBuffer buffer = IntBuffer.wrap(pixels); + gl.glReadPixels(0, 0, canvasWidth, canvasHeight, GL2.GL_BGRA, GlRenderer.bigEndian ? GL2.GL_UNSIGNED_INT_8_8_8_8_REV : GL2.GL_UNSIGNED_BYTE, buffer); + return pixels; + } + @OriginalMember(owner = "client!tf", name = "a", descriptor = "(Z)V") public static void setFogEnabled(@OriginalArg(0) boolean enabled) { if (enabled == fogEnabled) { diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 6e1adbb..983576d 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -34,17 +34,18 @@ import plugin.Plugin import plugin.api.* import plugin.api.API.* import plugin.api.FontColor.fromColor -import rt4.GameShell +import rt4.* import rt4.GameShell.canvas import rt4.GameShell.frame -import rt4.GlRenderer -import rt4.InterfaceList -import rt4.Player -import rt4.SoftwareRaster -import rt4.client.* +import rt4.client.js5Archive8 +import rt4.client.mainLoadState import java.awt.* +import java.awt.Font import java.awt.event.* +import java.awt.image.BufferedImage import java.awt.image.VolatileImage +import java.util.* +import java.util.Timer import javax.swing.* @@ -148,7 +149,7 @@ class plugin : Plugin() { } lastLogin = Player.usernameInput.toString() } - class AltCanvas(private val mainCanvas: Canvas) : JPanel() { + class AltCanvas() : JPanel() { private var gameImage: VolatileImage? = null private var scaleX = 1.0 private var scaleY = 1.0 @@ -186,19 +187,19 @@ class plugin : Plugin() { // Register a KeyAdapter for handling key events addKeyListener(object : KeyAdapter() { override fun keyPressed(e: KeyEvent) { - for (listener in mainCanvas.keyListeners) { + for (listener in canvas.keyListeners) { listener.keyPressed(e) } } override fun keyReleased(e: KeyEvent) { - for (listener in mainCanvas.keyListeners) { + for (listener in canvas.keyListeners) { listener.keyReleased(e) } } override fun keyTyped(e: KeyEvent) { - for (listener in mainCanvas.keyListeners) { + for (listener in canvas.keyListeners) { listener.keyTyped(e) } } @@ -287,27 +288,62 @@ class plugin : Plugin() { val originalY = adjustedY.toInt().coerceIn(0, gameImage!!.height - 1) val newEvent = MouseEvent( - mainCanvas, e.id, e.`when`, e.modifiersEx, + canvas, e.id, e.`when`, e.modifiersEx, originalX, originalY, e.clickCount, e.isPopupTrigger, e.button ) - mainCanvas.dispatchEvent(newEvent) + canvas.dispatchEvent(newEvent) } fun updateGameImage() { validateGameImage() + if (IsHD()) { + renderGlRaster() + } else { + renderSoftwareRaster() + } + repaint() + } + private fun renderGlRaster() { + val pixels = GlRenderer.pixelData // Assuming this holds the int[] BGRA pixel data from GlRenderer.readPixels() + val width = gameImage!!.width + val height = gameImage!!.height + + // Create a BufferedImage with the same dimensions as the gameImage + val bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_INT_BGR) + + // Flip the image vertically by reversing the rows + val flippedPixels = IntArray(width * height) + for (y in 0 until height) { + // Calculate the source row (bottom to top) + val srcY = height - 1 - y + System.arraycopy(pixels, srcY * width, flippedPixels, y * width, width) + } + + // Set the flipped pixel data into the BufferedImage + bufferedImage.setRGB(0, 0, width, height, flippedPixels, 0, width) + + // Draw the BufferedImage onto the VolatileImage + val g = gameImage!!.createGraphics() + try { + g.drawImage(bufferedImage, 0, 0, null) + } finally { + g.dispose() + } + } + + private fun renderSoftwareRaster() { val g = gameImage!!.createGraphics() try { SoftwareRaster.frameBuffer.draw(g) } finally { g.dispose() } - repaint() } } - fun createAltCanvas(mainCanvas: Canvas): AltCanvas { - return AltCanvas(mainCanvas).apply { + fun createAltCanvas(): AltCanvas { + return AltCanvas().apply { preferredSize = Dimension(FIXED_WIDTH, 503) } } @@ -323,14 +359,12 @@ class plugin : Plugin() { val frame: Frame? = GameShell.frame if (frame != null) { // Create the AltCanvas and add it to the main frame - altCanvas = createAltCanvas(canvas) - canvas.isVisible = false + altCanvas = createAltCanvas() // Use BorderLayout for better layout control frame.layout = BorderLayout() // Add the AltCanvas in the center to ensure it scales properly with the window size altCanvas?.let { frame.add(it, BorderLayout.NORTH) } - frame.remove(canvas) } } @@ -415,6 +449,20 @@ class plugin : Plugin() { frame.layout = BorderLayout() frame.add(rightPanelWrapper, BorderLayout.EAST) + // Create a timer to delay execution by 2 seconds + Timer().schedule(object : TimerTask() { + override fun run() { + println("mode is: " + GetWindowMode().toString()) + if (GetWindowMode() != WindowMode.FIXED) { + // Perform any actions needed for non-fixed mode + } else { + //if (canvas.isShowing) { + // frame.remove(canvas) + // } + } + } + }, 2000) // 2000 milliseconds = 2 seconds + frame.revalidate() frame.repaint() pluginsReloaded = true @@ -490,7 +538,8 @@ class plugin : Plugin() { } override fun LateDraw(timeDelta: Long){ - // Update game image here + // Clear original canvas for scaled + if(!initialized) return altCanvas?.updateGameImage() } From 4f8bf464c5fff02379dfc2df77043c01332a314e Mon Sep 17 00:00:00 2001 From: downthecrop Date: Fri, 25 Oct 2024 21:22:16 -0700 Subject: [PATCH 07/25] HD Resize redraw --- client/src/main/java/rt4/GameShell.java | 6 +++-- client/src/main/java/rt4/GlRenderer.java | 2 +- .../src/main/kotlin/KondoKit/plugin.kt | 25 +++++++------------ 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/client/src/main/java/rt4/GameShell.java b/client/src/main/java/rt4/GameShell.java index 9bd0bd6..250f826 100644 --- a/client/src/main/java/rt4/GameShell.java +++ b/client/src/main/java/rt4/GameShell.java @@ -182,6 +182,7 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene @OriginalMember(owner = "client!qh", name = "a", descriptor = "(Z)V") public static void method3662() { + System.out.println("Moving..."); @Pc(8) Container local8; if (fullScreenFrame != null) { local8 = fullScreenFrame; @@ -514,9 +515,10 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene canvasScale = getCurrentDevice().getDefaultConfiguration().getDefaultTransform().getScaleX(); if (frame != null && fullScreenFrame == null) { @Pc(84) Insets insets = frame.getInsets(); - canvas.setLocation(insets.left + leftMargin, topMargin + insets.top); + // TODO: Add a flag to ignore this. + //canvas.setLocation(insets.left + leftMargin, topMargin + insets.top); } else { - canvas.setLocation(leftMargin, topMargin); + //canvas.setLocation(leftMargin, topMargin); } } this.mainRedraw(); diff --git a/client/src/main/java/rt4/GlRenderer.java b/client/src/main/java/rt4/GlRenderer.java index c7a7d2a..3ad7392 100644 --- a/client/src/main/java/rt4/GlRenderer.java +++ b/client/src/main/java/rt4/GlRenderer.java @@ -203,7 +203,7 @@ public final class GlRenderer { try { pixelData = readPixels(); drawable.swapBuffers(); - } catch (@Pc(3) Exception local3) {*, + } catch (@Pc(3) Exception local3) { } } diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 983576d..d9a3cfd 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -44,8 +44,6 @@ import java.awt.Font import java.awt.event.* import java.awt.image.BufferedImage import java.awt.image.VolatileImage -import java.util.* -import java.util.Timer import javax.swing.* @@ -449,20 +447,6 @@ class plugin : Plugin() { frame.layout = BorderLayout() frame.add(rightPanelWrapper, BorderLayout.EAST) - // Create a timer to delay execution by 2 seconds - Timer().schedule(object : TimerTask() { - override fun run() { - println("mode is: " + GetWindowMode().toString()) - if (GetWindowMode() != WindowMode.FIXED) { - // Perform any actions needed for non-fixed mode - } else { - //if (canvas.isShowing) { - // frame.remove(canvas) - // } - } - } - }, 2000) // 2000 milliseconds = 2 seconds - frame.revalidate() frame.repaint() pluginsReloaded = true @@ -540,6 +524,15 @@ class plugin : Plugin() { override fun LateDraw(timeDelta: Long){ // Clear original canvas for scaled if(!initialized) return + SwingUtilities.invokeLater { + if (GetWindowMode() == WindowMode.FIXED) { + if (canvas.isShowing) { + canvas.setLocation(-1000,-1000) + } + } else { + + } + } altCanvas?.updateGameImage() } From 15deb6216ff871349c4e2212f8bd1efcd91e4aa2 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Fri, 25 Oct 2024 21:26:43 -0700 Subject: [PATCH 08/25] skip unrequired movement --- plugin-playground/src/main/kotlin/KondoKit/plugin.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index d9a3cfd..12d75cc 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -525,9 +525,11 @@ class plugin : Plugin() { // Clear original canvas for scaled if(!initialized) return SwingUtilities.invokeLater { + var p = Point(-1000,-1000) if (GetWindowMode() == WindowMode.FIXED) { - if (canvas.isShowing) { - canvas.setLocation(-1000,-1000) + if (canvas.location != p) { + println("Moving canvas offscreen"); + canvas.location = p; } } else { From 71afb2b385a563af892264ad8b96f60b7924729e Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sat, 26 Oct 2024 09:06:23 -0700 Subject: [PATCH 09/25] greatly reduce flickering --- client/src/main/java/rt4/DisplayMode.java | 6 - .../src/main/kotlin/KondoKit/HiscoresView.kt | 18 ++- .../main/kotlin/KondoKit/ScrollablePanel.kt | 76 ++++++------ .../src/main/kotlin/KondoKit/plugin.kt | 111 +++++++++++++----- 4 files changed, 131 insertions(+), 80 deletions(-) diff --git a/client/src/main/java/rt4/DisplayMode.java b/client/src/main/java/rt4/DisplayMode.java index 58bf779..440e79d 100644 --- a/client/src/main/java/rt4/DisplayMode.java +++ b/client/src/main/java/rt4/DisplayMode.java @@ -79,12 +79,6 @@ public final class DisplayMode { @OriginalMember(owner = "client!pm", name = "a", descriptor = "(ZIZIZII)V") public static void setWindowMode(@OriginalArg(0) boolean replaceCanvas, @OriginalArg(1) int newMode, @OriginalArg(2) boolean useHD, @OriginalArg(3) int currentMode, @OriginalArg(5) int width, @OriginalArg(6) int height) { - if(!GameShell.canvas.isShowing()){ - GameShell.frame.add(GameShell.canvas); - GameShell.canvas.revalidate(); - GameShell.frame.revalidate(); - GameShell.canvas.repaint(); - } if (useHD) { GlRenderer.quit(); } diff --git a/plugin-playground/src/main/kotlin/KondoKit/HiscoresView.kt b/plugin-playground/src/main/kotlin/KondoKit/HiscoresView.kt index ecdeed0..f192098 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/HiscoresView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/HiscoresView.kt @@ -7,9 +7,7 @@ import KondoKit.Helpers.formatHtmlLabelText import KondoKit.Helpers.getSpriteId import KondoKit.Helpers.showToast import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite -import KondoKit.plugin.Companion.POPUP_BACKGROUND import KondoKit.plugin.Companion.POPUP_FOREGROUND -import KondoKit.plugin.Companion.TITLE_BAR_COLOR import KondoKit.plugin.Companion.TOOLTIP_BACKGROUND import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR import KondoKit.plugin.Companion.WIDGET_COLOR @@ -112,7 +110,9 @@ object HiscoresView { } else { text += e.keyChar } - repaint() + SwingUtilities.invokeLater { + repaint() + } } override fun keyPressed(e: KeyEvent) { if (e.isControlDown) { @@ -125,7 +125,9 @@ object HiscoresView { val clipboard = Toolkit.getDefaultToolkit().systemClipboard val pasteText = clipboard.getData(DataFlavor.stringFlavor) as String text += pasteText - repaint() + SwingUtilities.invokeLater { + repaint() + } } } } @@ -136,7 +138,9 @@ object HiscoresView { override fun mouseClicked(e: MouseEvent) { if (e.x > width - 20 && e.y < 20) { text = "" - repaint() + SwingUtilities.invokeLater { + repaint() + } } } }) @@ -144,7 +148,9 @@ object HiscoresView { Timer(500) { cursorVisible = !cursorVisible if(focusedView == VIEW_NAME) - repaint() + SwingUtilities.invokeLater { + repaint() + } }.start() } diff --git a/plugin-playground/src/main/kotlin/KondoKit/ScrollablePanel.kt b/plugin-playground/src/main/kotlin/KondoKit/ScrollablePanel.kt index 46f2b5a..c190c1a 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/ScrollablePanel.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/ScrollablePanel.kt @@ -9,6 +9,7 @@ import java.awt.Rectangle import java.awt.event.* import java.util.* import javax.swing.JPanel +import javax.swing.SwingUtilities class ScrollablePanel(private val content: JPanel) : JPanel() { private var lastMouseY = 0 @@ -80,20 +81,22 @@ class ScrollablePanel(private val content: JPanel) : JPanel() { } private fun handleResize() { - // Ensure the ScrollablePanel resizes with the frame - bounds = Rectangle(0, 0, 242, frame.height) + SwingUtilities.invokeLater{ + // Ensure the ScrollablePanel resizes with the frame + bounds = Rectangle(0, 0, 242, frame.height) - // Dynamically update content bounds and scrollbar on frame resize with buffer - content.bounds = Rectangle(0, 0, 242, content.preferredSize.height.coerceAtLeast(frame.height + viewBuffer)) - showScrollbar = content.height > frame.height + // Dynamically update content bounds and scrollbar on frame resize with buffer + content.bounds = Rectangle(0, 0, 242, content.preferredSize.height.coerceAtLeast(frame.height + viewBuffer)) + showScrollbar = content.height > frame.height - currentOffsetY = 0 + currentOffsetY = 0 - content.setLocation(0, currentOffsetY) - updateScrollbar() + content.setLocation(0, currentOffsetY) + updateScrollbar() - revalidate() - repaint() + revalidate() + repaint() + } } private fun scrollContent(deltaY: Int) { @@ -102,40 +105,41 @@ class ScrollablePanel(private val content: JPanel) : JPanel() { content.setLocation(0, currentOffsetY) return } + SwingUtilities.invokeLater { + currentOffsetY += deltaY - currentOffsetY += deltaY + // Apply buffer to maxOffset + val maxOffset = (frame.height - content.height + viewBuffer).coerceAtMost(0) + currentOffsetY = currentOffsetY.coerceAtMost(0).coerceAtLeast(maxOffset) - // Apply buffer to maxOffset - val maxOffset = (frame.height - content.height + viewBuffer).coerceAtMost(0) - currentOffsetY = currentOffsetY.coerceAtMost(0).coerceAtLeast(maxOffset) + content.setLocation(0, currentOffsetY) - content.setLocation(0, currentOffsetY) - - val contentHeight = content.height - val viewHeight = frame.height + viewBuffer - val scrollableRatio = viewHeight.toDouble() / contentHeight - scrollbarY = ((-currentOffsetY / contentHeight.toDouble()) * viewHeight).toInt() - scrollbarHeight = (viewHeight * scrollableRatio).toInt().coerceAtLeast(20) - - repaint() - } - - private fun updateScrollbar() { - showScrollbar = content.height > frame.height - - val contentHeight = content.height - val viewHeight = frame.height + viewBuffer - - if (showScrollbar) { + val contentHeight = content.height + val viewHeight = frame.height + viewBuffer val scrollableRatio = viewHeight.toDouble() / contentHeight scrollbarY = ((-currentOffsetY / contentHeight.toDouble()) * viewHeight).toInt() scrollbarHeight = (viewHeight * scrollableRatio).toInt().coerceAtLeast(20) - } else { - scrollbarY = 0 - scrollbarHeight = 0 + repaint() } + } - repaint() + private fun updateScrollbar() { + SwingUtilities.invokeLater { + showScrollbar = content.height > frame.height + + val contentHeight = content.height + val viewHeight = frame.height + viewBuffer + + if (showScrollbar) { + val scrollableRatio = viewHeight.toDouble() / contentHeight + scrollbarY = ((-currentOffsetY / contentHeight.toDouble()) * viewHeight).toInt() + scrollbarHeight = (viewHeight * scrollableRatio).toInt().coerceAtLeast(20) + } else { + scrollbarY = 0 + scrollbarHeight = 0 + } + repaint() + } } override fun paintComponent(g: Graphics) { diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 12d75cc..fe6f249 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -147,7 +147,8 @@ class plugin : Plugin() { } lastLogin = Player.usernameInput.toString() } - class AltCanvas() : JPanel() { + + class AltCanvas : Canvas() { private var gameImage: VolatileImage? = null private var scaleX = 1.0 private var scaleY = 1.0 @@ -207,15 +208,19 @@ class plugin : Plugin() { requestFocusInWindow() } + override fun update(g: Graphics) { + paint(g) + } + private fun validateGameImage() { val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration if (gameImage == null) { - gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.TRANSLUCENT) + gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.OPAQUE) renderGameImage() } else { val status = gameImage!!.validate(gc) if (status == VolatileImage.IMAGE_INCOMPATIBLE) { - gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.TRANSLUCENT) + gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.OPAQUE) renderGameImage() } else if (status == VolatileImage.IMAGE_RESTORED) { renderGameImage() @@ -237,20 +242,35 @@ class plugin : Plugin() { } } - override fun paintComponent(g: Graphics) { - super.paintComponent(g) + override fun paint(g: Graphics) { val g2d = g as Graphics2D - - // Set the desired background fill color here g2d.color = Color.BLACK g2d.fillRect(0, 0, width, height) - validateGameImage() + // Validate image within paint to ensure compatibility with GraphicsConfiguration + var valid = false + do { + val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration + if (gameImage == null) { + gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.OPAQUE) + renderGameImage() + } else { + val status = gameImage!!.validate(gc) + when (status) { + VolatileImage.IMAGE_INCOMPATIBLE -> { + gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.OPAQUE) + renderGameImage() + } + VolatileImage.IMAGE_RESTORED -> renderGameImage() + VolatileImage.IMAGE_OK -> valid = true + } + } + } while (!valid) + // Continue with rendering the image gameImage?.let { image -> g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR) - - // Calculate aspect-ratio-preserving scale + // Scaling and centering val imageAspect = image.width.toDouble() / image.height.toDouble() val panelAspect = width.toDouble() / height.toDouble() @@ -289,7 +309,6 @@ class plugin : Plugin() { canvas, e.id, e.`when`, e.modifiersEx, originalX, originalY, e.clickCount, e.isPopupTrigger, e.button ) - canvas.dispatchEvent(newEvent) } @@ -383,8 +402,11 @@ class plugin : Plugin() { } } rightPanelWrapper?.preferredSize = Dimension(currentScrollPaneWidth, frame.height) + rightPanelWrapper?.let { it.isDoubleBuffered = true } rightPanelWrapper?.revalidate() - rightPanelWrapper?.repaint() + SwingUtilities.invokeLater { + rightPanelWrapper?.repaint() + } } fun OnKondoValueUpdated(){ @@ -446,9 +468,7 @@ class plugin : Plugin() { frame.remove(rightPanelWrapper) frame.layout = BorderLayout() frame.add(rightPanelWrapper, BorderLayout.EAST) - frame.revalidate() - frame.repaint() pluginsReloaded = true reloadInterfaces = true return true @@ -476,7 +496,9 @@ class plugin : Plugin() { xpTrackerView?.revalidate() if(focusedView == XPTrackerView.VIEW_NAME) - xpTrackerView?.repaint() + SwingUtilities.invokeLater { + xpTrackerView?.repaint() + } updateWidget(xpWidget, xp) } @@ -522,22 +544,35 @@ class plugin : Plugin() { } override fun LateDraw(timeDelta: Long){ - // Clear original canvas for scaled if(!initialized) return SwingUtilities.invokeLater { - var p = Point(-1000,-1000) if (GetWindowMode() == WindowMode.FIXED) { - if (canvas.location != p) { - println("Moving canvas offscreen"); - canvas.location = p; + if (canvas.parent !== hiddenFrame?.contentPane) { + println("Moving canvas to hidden frame") + initializeHiddenFrame() + frame.remove(canvas) // Remove from main frame if necessary + hiddenFrame?.contentPane?.add(canvas) + hiddenFrame?.pack() } - } else { - } } - altCanvas?.updateGameImage() + altCanvas?.updateGameImage() // Update the game image as needed } + private var hiddenFrame: JFrame? = null + + fun initializeHiddenFrame() { + if (hiddenFrame == null) { + hiddenFrame = JFrame().apply { + isUndecorated = true + isVisible = false // Keep it hidden + setSize(1, 1) // Minimal size + defaultCloseOperation = JFrame.DO_NOTHING_ON_CLOSE + } + } + } + + private fun initKondoUI(){ DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2) if(!allSpritesLoaded()) return; @@ -683,7 +718,9 @@ class plugin : Plugin() { val formattedXpPerHour = formatNumber(xpPerHour) xpWidget.xpPerHourLabel.text = formatHtmlLabelText("XP /hr: ", primaryColor, formattedXpPerHour, secondaryColor) - xpWidget.container.repaint() + SwingUtilities.invokeLater{ + xpWidget.container.repaint() + } } totalXP?.let { totalXPWidget -> @@ -692,7 +729,9 @@ class plugin : Plugin() { val formattedTotalXpPerHour = formatNumber(totalXPPerHour) totalXPWidget.xpPerHourLabel.text = formatHtmlLabelText("XP /hr: ", primaryColor, formattedTotalXpPerHour, secondaryColor) - totalXPWidget.container.repaint() + SwingUtilities.invokeLater{ + totalXPWidget.container.repaint() + } } } @@ -717,11 +756,14 @@ class plugin : Plugin() { // Revalidate and repaint necessary panels mainContentPanel.revalidate() - mainContentPanel.repaint() rightPanelWrapper?.revalidate() - rightPanelWrapper?.repaint() frame?.revalidate() - frame?.repaint() + + SwingUtilities.invokeLater{ + mainContentPanel.repaint() + rightPanelWrapper?.repaint() + frame?.repaint() + } focusedView = viewName } @@ -784,15 +826,20 @@ class plugin : Plugin() { override fun mouseEntered(e: MouseEvent?) { background = WIDGET_COLOR.darker() imageCanvas.fillColor = WIDGET_COLOR.darker() - imageCanvas.repaint() - repaint() + SwingUtilities.invokeLater{ + imageCanvas.repaint() + repaint() + } } override fun mouseExited(e: MouseEvent?) { background = WIDGET_COLOR imageCanvas.fillColor = WIDGET_COLOR - imageCanvas.repaint() - repaint() + SwingUtilities.invokeLater{ + imageCanvas.repaint() + repaint() + } + } override fun mouseClicked(e: MouseEvent?) { From 83fe4805acd2e70ef27abd958b29640bb4787ed4 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sat, 26 Oct 2024 09:59:25 -0700 Subject: [PATCH 10/25] GC issues + some late invokes --- client/src/main/java/rt4/GlRenderer.java | 35 ++++- .../src/main/kotlin/KondoKit/plugin.kt | 144 +++++++++--------- 2 files changed, 99 insertions(+), 80 deletions(-) diff --git a/client/src/main/java/rt4/GlRenderer.java b/client/src/main/java/rt4/GlRenderer.java index 3ad7392..3f564b3 100644 --- a/client/src/main/java/rt4/GlRenderer.java +++ b/client/src/main/java/rt4/GlRenderer.java @@ -9,6 +9,7 @@ import org.openrs2.deob.annotation.OriginalMember; import org.openrs2.deob.annotation.Pc; import java.awt.*; +import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import java.nio.charset.StandardCharsets; @@ -24,7 +25,10 @@ public final class GlRenderer { public static float hFOV = 0; - public static int[] pixelData = null; + + private static ByteBuffer pixelByteBuffer; + private static IntBuffer pixelIntBuffer; + public static int[] pixelData; @OriginalMember(owner = "client!tf", name = "c", descriptor = "F") private static float aFloat30; @@ -201,18 +205,33 @@ public final class GlRenderer { @OriginalMember(owner = "client!tf", name = "d", descriptor = "()V") public static void swapBuffers() { try { - pixelData = readPixels(); + readPixels(); drawable.swapBuffers(); } catch (@Pc(3) Exception local3) { } } - @OriginalMember(owner = "client!tf", name = "readPixels", descriptor = "()int[]") - public static int[] readPixels() { - int[] pixels = new int[canvasWidth * canvasHeight]; - IntBuffer buffer = IntBuffer.wrap(pixels); - gl.glReadPixels(0, 0, canvasWidth, canvasHeight, GL2.GL_BGRA, GlRenderer.bigEndian ? GL2.GL_UNSIGNED_INT_8_8_8_8_REV : GL2.GL_UNSIGNED_BYTE, buffer); - return pixels; + public static void initializePixelBuffer(int width, int height) { + // Allocate ByteBuffer for BGRA pixels (4 bytes per pixel) + pixelByteBuffer = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder()); + pixelIntBuffer = pixelByteBuffer.asIntBuffer(); + pixelData = new int[width * height]; + } + + public static void readPixels() { + // Ensure the pixel buffer is initialized with the correct size + if (pixelByteBuffer == null || pixelIntBuffer.capacity() != canvasWidth * canvasHeight) { + initializePixelBuffer(canvasWidth, canvasHeight); + } + + // Read pixels into the direct ByteBuffer + gl.glReadPixels(0, 0, canvasWidth, canvasHeight, GL2.GL_BGRA, + GlRenderer.bigEndian ? GL2.GL_UNSIGNED_INT_8_8_8_8_REV : GL2.GL_UNSIGNED_BYTE, + pixelByteBuffer); + + // Convert to int array if needed + pixelIntBuffer.rewind(); // Prepare the IntBuffer for reading + pixelIntBuffer.get(pixelData, 0, pixelData.length); // Transfer to pixelData array if necessary } @OriginalMember(owner = "client!tf", name = "a", descriptor = "(Z)V") diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index fe6f249..ea53905 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -150,6 +150,8 @@ class plugin : Plugin() { class AltCanvas : Canvas() { private var gameImage: VolatileImage? = null + private var flippedPixels: IntArray? = null + private var bufferImage: BufferedImage? = null private var scaleX = 1.0 private var scaleY = 1.0 private var offsetX = 0 @@ -158,6 +160,8 @@ class plugin : Plugin() { init { validateGameImage() + isFocusable = true + requestFocusInWindow() addMouseListener(object : MouseAdapter() { override fun mousePressed(e: MouseEvent) { @@ -212,6 +216,11 @@ class plugin : Plugin() { paint(g) } + override fun addNotify() { + super.addNotify() + //createBufferStrategy(2) // Double buffering for V-Sync, called only after the peer is created + } + private fun validateGameImage() { val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration if (gameImage == null) { @@ -294,6 +303,9 @@ class plugin : Plugin() { val x = offsetX val y = offsetY g2d.drawImage(image, x, y, drawWidth, drawHeight, null) + g2d.dispose() + //bufferStrategy.show() // Shows the buffer with V-Sync enabled + Toolkit.getDefaultToolkit().sync() // Ensures V-Sync on some systems } } @@ -322,30 +334,27 @@ class plugin : Plugin() { repaint() } private fun renderGlRaster() { - val pixels = GlRenderer.pixelData // Assuming this holds the int[] BGRA pixel data from GlRenderer.readPixels() - val width = gameImage!!.width - val height = gameImage!!.height - - // Create a BufferedImage with the same dimensions as the gameImage - val bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_INT_BGR) - - // Flip the image vertically by reversing the rows - val flippedPixels = IntArray(width * height) - for (y in 0 until height) { - // Calculate the source row (bottom to top) - val srcY = height - 1 - y - System.arraycopy(pixels, srcY * width, flippedPixels, y * width, width) + if (flippedPixels == null || flippedPixels!!.size != gameImage!!.width * gameImage!!.height) { + flippedPixels = IntArray(gameImage!!.width * gameImage!!.height) } - // Set the flipped pixel data into the BufferedImage - bufferedImage.setRGB(0, 0, width, height, flippedPixels, 0, width) + // Initialize bufferImage only once and reuse it + if (bufferImage == null || bufferImage!!.width != gameImage!!.width || bufferImage!!.height != gameImage!!.height) { + bufferImage = BufferedImage(gameImage!!.width, gameImage!!.height, BufferedImage.TYPE_INT_BGR) + } - // Draw the BufferedImage onto the VolatileImage - val g = gameImage!!.createGraphics() - try { - g.drawImage(bufferedImage, 0, 0, null) - } finally { - g.dispose() + val width = gameImage!!.width + val height = gameImage!!.height + val pixels = GlRenderer.pixelData // Retrieve BGRA pixel data + for (y in 0 until height) { + System.arraycopy(pixels, (height - 1 - y) * width, flippedPixels, y * width, width) + } + + bufferImage!!.setRGB(0, 0, width, height, flippedPixels, 0, width) + + gameImage?.createGraphics()?.apply { + drawImage(bufferImage, 0, 0, null) + dispose() } } @@ -404,9 +413,7 @@ class plugin : Plugin() { rightPanelWrapper?.preferredSize = Dimension(currentScrollPaneWidth, frame.height) rightPanelWrapper?.let { it.isDoubleBuffered = true } rightPanelWrapper?.revalidate() - SwingUtilities.invokeLater { - rightPanelWrapper?.repaint() - } + rightPanelWrapper?.repaint() } fun OnKondoValueUpdated(){ @@ -462,9 +469,7 @@ class plugin : Plugin() { override fun OnPluginsReloaded(): Boolean { if (!initialized) return true - UpdateDisplaySettings() - frame.remove(rightPanelWrapper) frame.layout = BorderLayout() frame.add(rightPanelWrapper, BorderLayout.EAST) @@ -475,32 +480,31 @@ class plugin : Plugin() { } override fun OnXPUpdate(skillId: Int, xp: Int) { - if (!initialXP.containsKey(skillId)) { - initialXP[skillId] = xp - return - } + SwingUtilities.invokeLater{ + if (!initialXP.containsKey(skillId)) { + initialXP[skillId] = xp + return@invokeLater + } + var xpWidget = xpWidgets[skillId] + if (xpWidget != null) { + updateWidget(xpWidget, xp) + } else { + val previousXp = initialXP[skillId] ?: xp + if (xp == initialXP[skillId]) return@invokeLater - var xpWidget = xpWidgets[skillId] + xpWidget = createXPWidget(skillId, previousXp) + xpWidgets[skillId] = xpWidget - if (xpWidget != null) { - updateWidget(xpWidget, xp) - } else { - val previousXp = initialXP[skillId] ?: xp - if (xp == initialXP[skillId]) return + xpTrackerView?.add(wrappedWidget(xpWidget.container)) + xpTrackerView?.add(Box.createVerticalStrut(5)) - xpWidget = createXPWidget(skillId, previousXp) - xpWidgets[skillId] = xpWidget - - xpTrackerView?.add(wrappedWidget(xpWidget.container)) - xpTrackerView?.add(Box.createVerticalStrut(5)) - - xpTrackerView?.revalidate() - if(focusedView == XPTrackerView.VIEW_NAME) - SwingUtilities.invokeLater { + if(focusedView == XPTrackerView.VIEW_NAME) { + xpTrackerView?.revalidate() xpTrackerView?.repaint() } - updateWidget(xpWidget, xp) + updateWidget(xpWidget, xp) + } } } @@ -545,16 +549,19 @@ class plugin : Plugin() { override fun LateDraw(timeDelta: Long){ if(!initialized) return - SwingUtilities.invokeLater { - if (GetWindowMode() == WindowMode.FIXED) { - if (canvas.parent !== hiddenFrame?.contentPane) { - println("Moving canvas to hidden frame") - initializeHiddenFrame() - frame.remove(canvas) // Remove from main frame if necessary - hiddenFrame?.contentPane?.add(canvas) - hiddenFrame?.pack() + if (GetWindowMode() == WindowMode.FIXED) { + if (canvas.parent !== hiddenFrame?.contentPane) { + if(altCanvas?.parent != frame) { + frame.add(altCanvas) } + println("Moving canvas to hidden frame") + initializeHiddenFrame() + frame.remove(canvas) // Remove from main frame if necessary + hiddenFrame?.contentPane?.add(canvas) + hiddenFrame?.pack() } + } else { + frame.remove(altCanvas) } altCanvas?.updateGameImage() // Update the game image as needed } @@ -716,9 +723,9 @@ class plugin : Plugin() { val elapsedTime = (System.currentTimeMillis() - xpWidget.startTime) / 1000.0 / 60.0 / 60.0 val xpPerHour = if (elapsedTime > 0) (xpWidget.totalXpGained / elapsedTime).toInt() else 0 val formattedXpPerHour = formatNumber(xpPerHour) - xpWidget.xpPerHourLabel.text = - formatHtmlLabelText("XP /hr: ", primaryColor, formattedXpPerHour, secondaryColor) SwingUtilities.invokeLater{ + xpWidget.xpPerHourLabel.text = + formatHtmlLabelText("XP /hr: ", primaryColor, formattedXpPerHour, secondaryColor) xpWidget.container.repaint() } } @@ -727,9 +734,9 @@ class plugin : Plugin() { val elapsedTime = (System.currentTimeMillis() - totalXPWidget.startTime) / 1000.0 / 60.0 / 60.0 val totalXPPerHour = if (elapsedTime > 0) (totalXPWidget.totalXpGained / elapsedTime).toInt() else 0 val formattedTotalXpPerHour = formatNumber(totalXPPerHour) - totalXPWidget.xpPerHourLabel.text = - formatHtmlLabelText("XP /hr: ", primaryColor, formattedTotalXpPerHour, secondaryColor) SwingUtilities.invokeLater{ + totalXPWidget.xpPerHourLabel.text = + formatHtmlLabelText("XP /hr: ", primaryColor, formattedTotalXpPerHour, secondaryColor) totalXPWidget.container.repaint() } } @@ -759,11 +766,9 @@ class plugin : Plugin() { rightPanelWrapper?.revalidate() frame?.revalidate() - SwingUtilities.invokeLater{ - mainContentPanel.repaint() - rightPanelWrapper?.repaint() - frame?.repaint() - } + mainContentPanel.repaint() + rightPanelWrapper?.repaint() + frame?.repaint() focusedView = viewName } @@ -826,20 +831,15 @@ class plugin : Plugin() { override fun mouseEntered(e: MouseEvent?) { background = WIDGET_COLOR.darker() imageCanvas.fillColor = WIDGET_COLOR.darker() - SwingUtilities.invokeLater{ - imageCanvas.repaint() - repaint() - } + imageCanvas.repaint() + repaint() } override fun mouseExited(e: MouseEvent?) { background = WIDGET_COLOR imageCanvas.fillColor = WIDGET_COLOR - SwingUtilities.invokeLater{ - imageCanvas.repaint() - repaint() - } - + imageCanvas.repaint() + repaint() } override fun mouseClicked(e: MouseEvent?) { From e7f46f1006ab0e8c4c65da928e46021a2589e108 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sat, 26 Oct 2024 22:31:43 -0700 Subject: [PATCH 11/25] Constant for FIXED_HEIGHT + transfercomponent helper --- .../src/main/kotlin/KondoKit/plugin.kt | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index ea53905..9fe4ef7 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -40,6 +40,7 @@ import rt4.GameShell.frame import rt4.client.js5Archive8 import rt4.client.mainLoadState import java.awt.* +import java.awt.Component import java.awt.Font import java.awt.event.* import java.awt.image.BufferedImage @@ -91,6 +92,7 @@ class plugin : Plugin() { var uiOffset = 0 private const val FIXED_WIDTH = 765 + private const val FIXED_HEIGHT = 503 private const val NAVBAR_WIDTH = 30 private const val MAIN_CONTENT_WIDTH = 242 private const val WRENCH_ICON = 907 @@ -111,6 +113,7 @@ class plugin : Plugin() { private var lastUIOffset = 0 private const val HIDDEN_VIEW = "HIDDEN" private val drawActions = mutableListOf<() -> Unit>() + private var hiddenFrame: JFrame? = null fun registerDrawAction(action: () -> Unit) { synchronized(drawActions) { @@ -224,12 +227,12 @@ class plugin : Plugin() { private fun validateGameImage() { val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration if (gameImage == null) { - gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.OPAQUE) + gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) renderGameImage() } else { val status = gameImage!!.validate(gc) if (status == VolatileImage.IMAGE_INCOMPATIBLE) { - gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.OPAQUE) + gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) renderGameImage() } else if (status == VolatileImage.IMAGE_RESTORED) { renderGameImage() @@ -261,13 +264,13 @@ class plugin : Plugin() { do { val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration if (gameImage == null) { - gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.OPAQUE) + gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) renderGameImage() } else { val status = gameImage!!.validate(gc) when (status) { VolatileImage.IMAGE_INCOMPATIBLE -> { - gameImage = gc.createCompatibleVolatileImage(765, 503, Transparency.OPAQUE) + gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) renderGameImage() } VolatileImage.IMAGE_RESTORED -> renderGameImage() @@ -370,7 +373,7 @@ class plugin : Plugin() { fun createAltCanvas(): AltCanvas { return AltCanvas().apply { - preferredSize = Dimension(FIXED_WIDTH, 503) + preferredSize = Dimension(FIXED_WIDTH, FIXED_HEIGHT) } } @@ -547,39 +550,51 @@ class plugin : Plugin() { } } - override fun LateDraw(timeDelta: Long){ - if(!initialized) return + override fun LateDraw(timeDelta: Long) { + if (!initialized) return if (GetWindowMode() == WindowMode.FIXED) { - if (canvas.parent !== hiddenFrame?.contentPane) { - if(altCanvas?.parent != frame) { + if (canvas.parent != hiddenFrame?.contentPane) { + if (altCanvas?.parent != frame) { frame.add(altCanvas) } - println("Moving canvas to hidden frame") initializeHiddenFrame() - frame.remove(canvas) // Remove from main frame if necessary - hiddenFrame?.contentPane?.add(canvas) - hiddenFrame?.pack() + hiddenFrame?.let { transferComponent(canvas, frame, it) } } } else { - frame.remove(altCanvas) + if (altCanvas?.parent == frame) { + frame.remove(altCanvas) + } } altCanvas?.updateGameImage() // Update the game image as needed } - private var hiddenFrame: JFrame? = null - fun initializeHiddenFrame() { + fun transferComponent(component: Component, fromFrame: Frame, toFrame: Frame) { + println("Transferring component") + fromFrame.remove(component) + toFrame.add(component) + toFrame.pack() + fromFrame.revalidate() + toFrame.revalidate() + fromFrame.repaint() + toFrame.repaint() + } + + fun initializeHiddenFrame(debugMode: Boolean = true) { if (hiddenFrame == null) { hiddenFrame = JFrame().apply { - isUndecorated = true - isVisible = false // Keep it hidden - setSize(1, 1) // Minimal size + isUndecorated = !debugMode + isFocusable = false + isVisible = debugMode // Show frame if debugMode is true + setSize( + if(debugMode) FIXED_WIDTH else 1, + if(debugMode) FIXED_HEIGHT else 1 + ) defaultCloseOperation = JFrame.DO_NOTHING_ON_CLOSE } } } - private fun initKondoUI(){ DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2) if(!allSpritesLoaded()) return; From 8180e202814794f346d1437d328b86e9042dbbaa Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sat, 26 Oct 2024 22:33:54 -0700 Subject: [PATCH 12/25] Removing debug from client + add print for unparented altcanvas --- client/src/main/java/rt4/GameShell.java | 1 - plugin-playground/src/main/kotlin/KondoKit/plugin.kt | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/rt4/GameShell.java b/client/src/main/java/rt4/GameShell.java index 250f826..68e6c32 100644 --- a/client/src/main/java/rt4/GameShell.java +++ b/client/src/main/java/rt4/GameShell.java @@ -182,7 +182,6 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene @OriginalMember(owner = "client!qh", name = "a", descriptor = "(Z)V") public static void method3662() { - System.out.println("Moving..."); @Pc(8) Container local8; if (fullScreenFrame != null) { local8 = fullScreenFrame; diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 9fe4ef7..cd2b50a 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -328,6 +328,9 @@ class plugin : Plugin() { } fun updateGameImage() { + if(this.parent == null) { + println("Unparented.. skipping update.") + } validateGameImage() if (IsHD()) { renderGlRaster() From 1f1718d9179ec44cf82aef13571ffeccfecceae1 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sun, 27 Oct 2024 08:10:38 -0700 Subject: [PATCH 13/25] Keep the canvas in the frame but change the Z order --- .../main/java/plugin/PluginRepository.java | 6 +- client/src/main/java/rt4/GlRenderer.java | 2 +- .../src/main/kotlin/KondoKit/plugin.kt | 65 +++++-------------- 3 files changed, 20 insertions(+), 53 deletions(-) diff --git a/client/src/main/java/plugin/PluginRepository.java b/client/src/main/java/plugin/PluginRepository.java index 55faf80..4225c8c 100644 --- a/client/src/main/java/plugin/PluginRepository.java +++ b/client/src/main/java/plugin/PluginRepository.java @@ -70,7 +70,7 @@ public class PluginRepository { File pluginsDirectory = new File(GlobalJsonConfig.instance.pluginsFolder); if (!pluginsDirectory.exists()) { - System.out.println("Skipping plugin initialization - " + pluginsDirectory.getAbsolutePath() + " does not exist."); + //System.out.println("Skipping plugin initialization - " + pluginsDirectory.getAbsolutePath() + " does not exist."); return; } @@ -120,7 +120,7 @@ public class PluginRepository { } if (loadedPlugins.containsKey(info)) { - System.out.println("Skipping reloading of plugin " + file.getName() + " as it already exists and has OnPluginsReloaded."); + //System.out.println("Skipping reloading of plugin " + file.getName() + " as it already exists and has OnPluginsReloaded."); continue; } @@ -143,7 +143,7 @@ public class PluginRepository { loader.loadClass(file.getName() + "." + f.getName().replace(".class","")); } - System.out.println("Successfully loaded plugin " + file.getName() + ", version " + info.version); + //System.out.println("Successfully loaded plugin " + file.getName() + ", version " + info.version); } } catch (Exception e) { System.err.println("Unexpected exception during plugin initialization:"); diff --git a/client/src/main/java/rt4/GlRenderer.java b/client/src/main/java/rt4/GlRenderer.java index 3f564b3..d644740 100644 --- a/client/src/main/java/rt4/GlRenderer.java +++ b/client/src/main/java/rt4/GlRenderer.java @@ -205,8 +205,8 @@ public final class GlRenderer { @OriginalMember(owner = "client!tf", name = "d", descriptor = "()V") public static void swapBuffers() { try { - readPixels(); drawable.swapBuffers(); + readPixels(); } catch (@Pc(3) Exception local3) { } } diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index cd2b50a..2635755 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -40,7 +40,6 @@ import rt4.GameShell.frame import rt4.client.js5Archive8 import rt4.client.mainLoadState import java.awt.* -import java.awt.Component import java.awt.Font import java.awt.event.* import java.awt.image.BufferedImage @@ -113,7 +112,6 @@ class plugin : Plugin() { private var lastUIOffset = 0 private const val HIDDEN_VIEW = "HIDDEN" private val drawActions = mutableListOf<() -> Unit>() - private var hiddenFrame: JFrame? = null fun registerDrawAction(action: () -> Unit) { synchronized(drawActions) { @@ -390,13 +388,13 @@ class plugin : Plugin() { System.setProperty("swing.aatext", "false") val frame: Frame? = GameShell.frame if (frame != null) { + frame.layout = BorderLayout() // Create the AltCanvas and add it to the main frame altCanvas = createAltCanvas() + altCanvas?.let { frame.add(it) } // Use BorderLayout for better layout control - frame.layout = BorderLayout() - - // Add the AltCanvas in the center to ensure it scales properly with the window size - altCanvas?.let { frame.add(it, BorderLayout.NORTH) } + frame.setComponentZOrder(altCanvas, 0) + frame.setComponentZOrder(canvas, 1) } } @@ -409,6 +407,7 @@ class plugin : Plugin() { if (frame.width < FIXED_WIDTH + currentScrollPaneWidth + uiOffset) { frame.setSize(FIXED_WIDTH + currentScrollPaneWidth + uiOffset, frame.height) } + canvas.setLocation(0,0) val difference = frame.width - (uiOffset + currentScrollPaneWidth) altCanvas?.size = Dimension(difference, frame.height - 30) } @@ -486,17 +485,16 @@ class plugin : Plugin() { } override fun OnXPUpdate(skillId: Int, xp: Int) { - SwingUtilities.invokeLater{ if (!initialXP.containsKey(skillId)) { initialXP[skillId] = xp - return@invokeLater + return } var xpWidget = xpWidgets[skillId] if (xpWidget != null) { updateWidget(xpWidget, xp) } else { val previousXp = initialXP[skillId] ?: xp - if (xp == initialXP[skillId]) return@invokeLater + if (xp == initialXP[skillId]) return xpWidget = createXPWidget(skillId, previousXp) xpWidgets[skillId] = xpWidget @@ -511,7 +509,6 @@ class plugin : Plugin() { updateWidget(xpWidget, xp) } - } } override fun Draw(timeDelta: Long) { @@ -555,49 +552,16 @@ class plugin : Plugin() { override fun LateDraw(timeDelta: Long) { if (!initialized) return - if (GetWindowMode() == WindowMode.FIXED) { - if (canvas.parent != hiddenFrame?.contentPane) { - if (altCanvas?.parent != frame) { - frame.add(altCanvas) - } - initializeHiddenFrame() - hiddenFrame?.let { transferComponent(canvas, frame, it) } - } + if(GetWindowMode() == WindowMode.RESIZABLE){ + frame.setComponentZOrder(altCanvas, 1) + frame.setComponentZOrder(canvas, 0) } else { - if (altCanvas?.parent == frame) { - frame.remove(altCanvas) - } + frame.setComponentZOrder(altCanvas, 0) + frame.setComponentZOrder(canvas, 1) } altCanvas?.updateGameImage() // Update the game image as needed } - - fun transferComponent(component: Component, fromFrame: Frame, toFrame: Frame) { - println("Transferring component") - fromFrame.remove(component) - toFrame.add(component) - toFrame.pack() - fromFrame.revalidate() - toFrame.revalidate() - fromFrame.repaint() - toFrame.repaint() - } - - fun initializeHiddenFrame(debugMode: Boolean = true) { - if (hiddenFrame == null) { - hiddenFrame = JFrame().apply { - isUndecorated = !debugMode - isFocusable = false - isVisible = debugMode // Show frame if debugMode is true - setSize( - if(debugMode) FIXED_WIDTH else 1, - if(debugMode) FIXED_HEIGHT else 1 - ) - defaultCloseOperation = JFrame.DO_NOTHING_ON_CLOSE - } - } - } - private fun initKondoUI(){ DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2) if(!allSpritesLoaded()) return; @@ -720,7 +684,10 @@ class plugin : Plugin() { } frame.layout = BorderLayout() - rightPanelWrapper?.let { frame.add(it, BorderLayout.EAST) } + rightPanelWrapper?.let { + frame.add(it, BorderLayout.EAST) + frame.setComponentZOrder(it, 2) + } if(!launchMinimized){ setActiveView(XPTrackerView.VIEW_NAME) From 341d6758c152719ee4c15115c5cf35a5ebcfbfef Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sun, 27 Oct 2024 19:40:24 -0700 Subject: [PATCH 14/25] Simplify altcanvas --- .../src/main/kotlin/KondoKit/plugin.kt | 238 ++++++------------ 1 file changed, 77 insertions(+), 161 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 2635755..a16e748 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -35,6 +35,7 @@ import plugin.api.* import plugin.api.API.* import plugin.api.FontColor.fromColor import rt4.* +import rt4.DisplayMode import rt4.GameShell.canvas import rt4.GameShell.frame import rt4.client.js5Archive8 @@ -111,6 +112,7 @@ class plugin : Plugin() { private var lastClickTime = 0L private var lastUIOffset = 0 private const val HIDDEN_VIEW = "HIDDEN" + private var altCanvas: AltCanvas? = null private val drawActions = mutableListOf<() -> Unit>() fun registerDrawAction(action: () -> Unit) { @@ -151,104 +153,64 @@ class plugin : Plugin() { class AltCanvas : Canvas() { private var gameImage: VolatileImage? = null - private var flippedPixels: IntArray? = null - private var bufferImage: BufferedImage? = null + private var flippedPixels = IntArray(FIXED_WIDTH * FIXED_HEIGHT) + private var bufferImage = BufferedImage(FIXED_WIDTH, FIXED_HEIGHT, BufferedImage.TYPE_INT_BGR) private var scaleX = 1.0 private var scaleY = 1.0 private var offsetX = 0 private var offsetY = 0 - init { - validateGameImage() isFocusable = true requestFocusInWindow() addMouseListener(object : MouseAdapter() { - override fun mousePressed(e: MouseEvent) { - relayMouseEvent(e) - } - - override fun mouseReleased(e: MouseEvent) { - relayMouseEvent(e) - } - - override fun mouseClicked(e: MouseEvent) { - relayMouseEvent(e) - } + override fun mousePressed(e: MouseEvent) = relayMouseEvent(e) + override fun mouseReleased(e: MouseEvent) = relayMouseEvent(e) + override fun mouseClicked(e: MouseEvent) = relayMouseEvent(e) }) addMouseMotionListener(object : MouseMotionAdapter() { - override fun mouseMoved(e: MouseEvent) { - relayMouseEvent(e) - } - - override fun mouseDragged(e: MouseEvent) { - relayMouseEvent(e) - } + override fun mouseMoved(e: MouseEvent) = relayMouseEvent(e) + override fun mouseDragged(e: MouseEvent) = relayMouseEvent(e) }) - // Register a KeyAdapter for handling key events addKeyListener(object : KeyAdapter() { - override fun keyPressed(e: KeyEvent) { - for (listener in canvas.keyListeners) { - listener.keyPressed(e) - } - } - - override fun keyReleased(e: KeyEvent) { - for (listener in canvas.keyListeners) { - listener.keyReleased(e) - } - } - - override fun keyTyped(e: KeyEvent) { - for (listener in canvas.keyListeners) { - listener.keyTyped(e) - } - } + override fun keyPressed(e: KeyEvent) = relayKeyEvent(e) { it.keyPressed(e) } + override fun keyReleased(e: KeyEvent) = relayKeyEvent(e) { it.keyReleased(e) } + override fun keyTyped(e: KeyEvent) = relayKeyEvent(e) { it.keyTyped(e) } }) - - isFocusable = true - requestFocusInWindow() } - override fun update(g: Graphics) { - paint(g) - } + override fun update(g: Graphics) = paint(g) override fun addNotify() { super.addNotify() - //createBufferStrategy(2) // Double buffering for V-Sync, called only after the peer is created + validateGameImage() } private fun validateGameImage() { val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration - if (gameImage == null) { - gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) - renderGameImage() - } else { - val status = gameImage!!.validate(gc) - if (status == VolatileImage.IMAGE_INCOMPATIBLE) { - gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) - renderGameImage() - } else if (status == VolatileImage.IMAGE_RESTORED) { - renderGameImage() + gameImage?.let { + when (it.validate(gc)) { + VolatileImage.IMAGE_INCOMPATIBLE -> createGameImage(gc) + VolatileImage.IMAGE_RESTORED -> renderGameImage() } - } + } ?: createGameImage(gc) + } + + private fun createGameImage(gc: GraphicsConfiguration) { + gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) + renderGameImage() } private fun renderGameImage() { - val g = gameImage!!.createGraphics() - try { - // Initial drawing code - g.color = Color.RED - g.fillRect(0, 0, gameImage!!.width, gameImage!!.height) - g.color = Color.BLACK - g.drawString("Game Frame", 20, 20) - // Add any additional rendering here - } finally { - g.dispose() + gameImage?.createGraphics()?.apply { + color = Color.RED + fillRect(0, 0, gameImage!!.width, gameImage!!.height) + color = Color.BLACK + drawString("Game Frame", 20, 20) + dispose() } } @@ -257,104 +219,58 @@ class plugin : Plugin() { g2d.color = Color.BLACK g2d.fillRect(0, 0, width, height) - // Validate image within paint to ensure compatibility with GraphicsConfiguration - var valid = false - do { - val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration - if (gameImage == null) { - gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) - renderGameImage() - } else { - val status = gameImage!!.validate(gc) - when (status) { - VolatileImage.IMAGE_INCOMPATIBLE -> { - gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) - renderGameImage() - } - VolatileImage.IMAGE_RESTORED -> renderGameImage() - VolatileImage.IMAGE_OK -> valid = true - } - } - } while (!valid) - - // Continue with rendering the image gameImage?.let { image -> g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR) - // Scaling and centering - val imageAspect = image.width.toDouble() / image.height.toDouble() - val panelAspect = width.toDouble() / height.toDouble() - - val (drawWidth, drawHeight) = if (imageAspect > panelAspect) { - val newWidth = width - val newHeight = (width / imageAspect).toInt() - newWidth to newHeight - } else { - val newHeight = height - val newWidth = (height * imageAspect).toInt() - newWidth to newHeight - } - - // Store scale factors and offsets for event adjustment + val (drawWidth, drawHeight) = calculateDrawDimensions(image) scaleX = drawWidth.toDouble() / image.width scaleY = drawHeight.toDouble() / image.height offsetX = (width - drawWidth) / 2 offsetY = (height - drawHeight) / 2 + g2d.drawImage(image, offsetX, offsetY, drawWidth, drawHeight, null) + Toolkit.getDefaultToolkit().sync() + } + } - // Draw the scaled image centered in the panel - val x = offsetX - val y = offsetY - g2d.drawImage(image, x, y, drawWidth, drawHeight, null) - g2d.dispose() - //bufferStrategy.show() // Shows the buffer with V-Sync enabled - Toolkit.getDefaultToolkit().sync() // Ensures V-Sync on some systems + private fun calculateDrawDimensions(image: VolatileImage): Pair { + val imageAspect = image.width.toDouble() / image.height.toDouble() + val panelAspect = width.toDouble() / height.toDouble() + return if (imageAspect > panelAspect) { + width to (width / imageAspect).toInt() + } else { + (height * imageAspect).toInt() to height } } private fun relayMouseEvent(e: MouseEvent) { - this.requestFocusInWindow() - val adjustedX = (e.x - offsetX) / scaleX - val adjustedY = (e.y - offsetY) / scaleY + requestFocusInWindow() + val adjustedX = ((e.x - offsetX) / scaleX).toInt().coerceIn(0, gameImage!!.width - 1) + val adjustedY = ((e.y - offsetY) / scaleY).toInt().coerceIn(0, gameImage!!.height - 1) + canvas.dispatchEvent(MouseEvent(canvas, e.id, e.`when`, e.modifiersEx, adjustedX, adjustedY, e.clickCount, e.isPopupTrigger, e.button)) + } - val originalX = adjustedX.toInt().coerceIn(0, gameImage!!.width - 1) - val originalY = adjustedY.toInt().coerceIn(0, gameImage!!.height - 1) - - val newEvent = MouseEvent( - canvas, e.id, e.`when`, e.modifiersEx, - originalX, originalY, e.clickCount, e.isPopupTrigger, e.button - ) - canvas.dispatchEvent(newEvent) + private fun relayKeyEvent(e: KeyEvent, action: (KeyListener) -> Unit) { + for (listener in canvas.keyListeners) action(listener) } fun updateGameImage() { - if(this.parent == null) { - println("Unparented.. skipping update.") - } - validateGameImage() - if (IsHD()) { - renderGlRaster() - } else { - renderSoftwareRaster() - } + if (IsHD()) renderGlRaster() else renderSoftwareRaster() repaint() } + private fun renderGlRaster() { - if (flippedPixels == null || flippedPixels!!.size != gameImage!!.width * gameImage!!.height) { - flippedPixels = IntArray(gameImage!!.width * gameImage!!.height) - } - - // Initialize bufferImage only once and reuse it - if (bufferImage == null || bufferImage!!.width != gameImage!!.width || bufferImage!!.height != gameImage!!.height) { - bufferImage = BufferedImage(gameImage!!.width, gameImage!!.height, BufferedImage.TYPE_INT_BGR) - } - val width = gameImage!!.width val height = gameImage!!.height - val pixels = GlRenderer.pixelData // Retrieve BGRA pixel data + val pixelData = GlRenderer.pixelData + + // Flip and copy pixels in one pass using a single loop for (y in 0 until height) { - System.arraycopy(pixels, (height - 1 - y) * width, flippedPixels, y * width, width) + val srcOffset = (height - 1 - y) * width + val destOffset = y * width + System.arraycopy(pixelData, srcOffset, flippedPixels, destOffset, width) } - bufferImage!!.setRGB(0, 0, width, height, flippedPixels, 0, width) + // Draw flipped pixels directly to bufferImage + bufferImage.setRGB(0, 0, width, height, flippedPixels, 0, width) gameImage?.createGraphics()?.apply { drawImage(bufferImage, 0, 0, null) @@ -363,23 +279,19 @@ class plugin : Plugin() { } private fun renderSoftwareRaster() { - val g = gameImage!!.createGraphics() - try { - SoftwareRaster.frameBuffer.draw(g) - } finally { - g.dispose() + gameImage?.createGraphics()?.apply { + SoftwareRaster.frameBuffer.draw(this) + dispose() } } } - fun createAltCanvas(): AltCanvas { + private fun createAltCanvas(): AltCanvas { return AltCanvas().apply { preferredSize = Dimension(FIXED_WIDTH, FIXED_HEIGHT) } } - private var altCanvas: AltCanvas? = null - override fun Init() { // Disable Font AA @@ -552,6 +464,14 @@ class plugin : Plugin() { override fun LateDraw(timeDelta: Long) { if (!initialized) return + if(GameShell.fullScreenFrame != null) { + DisplayMode.setWindowMode(true, 0, FIXED_WIDTH, FIXED_HEIGHT) + showAlert("Fullscreen is not supported by KondoKit. Disable the plugin", + "Error", + JOptionPane.INFORMATION_MESSAGE + ) + return; + } if(GetWindowMode() == WindowMode.RESIZABLE){ frame.setComponentZOrder(altCanvas, 1) frame.setComponentZOrder(canvas, 0) @@ -708,22 +628,18 @@ class plugin : Plugin() { val elapsedTime = (System.currentTimeMillis() - xpWidget.startTime) / 1000.0 / 60.0 / 60.0 val xpPerHour = if (elapsedTime > 0) (xpWidget.totalXpGained / elapsedTime).toInt() else 0 val formattedXpPerHour = formatNumber(xpPerHour) - SwingUtilities.invokeLater{ - xpWidget.xpPerHourLabel.text = - formatHtmlLabelText("XP /hr: ", primaryColor, formattedXpPerHour, secondaryColor) - xpWidget.container.repaint() - } + xpWidget.xpPerHourLabel.text = + formatHtmlLabelText("XP /hr: ", primaryColor, formattedXpPerHour, secondaryColor) + xpWidget.container.repaint() } totalXP?.let { totalXPWidget -> val elapsedTime = (System.currentTimeMillis() - totalXPWidget.startTime) / 1000.0 / 60.0 / 60.0 val totalXPPerHour = if (elapsedTime > 0) (totalXPWidget.totalXpGained / elapsedTime).toInt() else 0 val formattedTotalXpPerHour = formatNumber(totalXPPerHour) - SwingUtilities.invokeLater{ - totalXPWidget.xpPerHourLabel.text = - formatHtmlLabelText("XP /hr: ", primaryColor, formattedTotalXpPerHour, secondaryColor) - totalXPWidget.container.repaint() - } + totalXPWidget.xpPerHourLabel.text = + formatHtmlLabelText("XP /hr: ", primaryColor, formattedTotalXpPerHour, secondaryColor) + totalXPWidget.container.repaint() } } From c5ba4ecc94a2361f6d6562c32b0c1076b3117b74 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sun, 27 Oct 2024 20:11:25 -0700 Subject: [PATCH 15/25] true nn upscale --- .../src/main/kotlin/KondoKit/plugin.kt | 45 +++++++++---------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index a16e748..aa3c242 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -43,6 +43,8 @@ import rt4.client.mainLoadState import java.awt.* import java.awt.Font import java.awt.event.* +import java.awt.geom.AffineTransform +import java.awt.image.AffineTransformOp import java.awt.image.BufferedImage import java.awt.image.VolatileImage import javax.swing.* @@ -153,12 +155,7 @@ class plugin : Plugin() { class AltCanvas : Canvas() { private var gameImage: VolatileImage? = null - private var flippedPixels = IntArray(FIXED_WIDTH * FIXED_HEIGHT) private var bufferImage = BufferedImage(FIXED_WIDTH, FIXED_HEIGHT, BufferedImage.TYPE_INT_BGR) - private var scaleX = 1.0 - private var scaleY = 1.0 - private var offsetX = 0 - private var offsetY = 0 init { isFocusable = true @@ -220,13 +217,10 @@ class plugin : Plugin() { g2d.fillRect(0, 0, width, height) gameImage?.let { image -> - g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR) - val (drawWidth, drawHeight) = calculateDrawDimensions(image) - scaleX = drawWidth.toDouble() / image.width - scaleY = drawHeight.toDouble() / image.height - offsetX = (width - drawWidth) / 2 - offsetY = (height - drawHeight) / 2 - g2d.drawImage(image, offsetX, offsetY, drawWidth, drawHeight, null) + val scale = minOf(width.toDouble() / image.width, height.toDouble() / image.height) + val x = ((width - image.width * scale) / 2).toInt() + val y = ((height - image.height * scale) / 2).toInt() + g2d.drawImage(image, x, y, (image.width * scale).toInt(), (image.height * scale).toInt(), null) Toolkit.getDefaultToolkit().sync() } } @@ -243,9 +237,14 @@ class plugin : Plugin() { private fun relayMouseEvent(e: MouseEvent) { requestFocusInWindow() - val adjustedX = ((e.x - offsetX) / scaleX).toInt().coerceIn(0, gameImage!!.width - 1) - val adjustedY = ((e.y - offsetY) / scaleY).toInt().coerceIn(0, gameImage!!.height - 1) - canvas.dispatchEvent(MouseEvent(canvas, e.id, e.`when`, e.modifiersEx, adjustedX, adjustedY, e.clickCount, e.isPopupTrigger, e.button)) + val scale = minOf(width.toDouble() / gameImage!!.width, height.toDouble() / gameImage!!.height) + val xOffset = ((width - gameImage!!.width * scale) / 2) + val yOffset = ((height - gameImage!!.height * scale) / 2) + + val adjustedX = ((e.x - xOffset) / scale).toInt().coerceIn(0, gameImage!!.width - 1) + val adjustedY = ((e.y - yOffset) / scale).toInt().coerceIn(0, gameImage!!.height - 1) + + canvas.dispatchEvent(MouseEvent(this, e.id, e.`when`, e.modifiersEx, adjustedX, adjustedY, e.clickCount, e.isPopupTrigger, e.button)) } private fun relayKeyEvent(e: KeyEvent, action: (KeyListener) -> Unit) { @@ -262,22 +261,20 @@ class plugin : Plugin() { val height = gameImage!!.height val pixelData = GlRenderer.pixelData - // Flip and copy pixels in one pass using a single loop - for (y in 0 until height) { - val srcOffset = (height - 1 - y) * width - val destOffset = y * width - System.arraycopy(pixelData, srcOffset, flippedPixels, destOffset, width) - } + bufferImage.setRGB(0, 0, width, height, pixelData, 0, width) - // Draw flipped pixels directly to bufferImage - bufferImage.setRGB(0, 0, width, height, flippedPixels, 0, width) + val transform = AffineTransform.getScaleInstance(1.0, -1.0) + transform.translate(0.0, -height.toDouble()) + val op = AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR) + val flippedImage = op.filter(bufferImage, null) gameImage?.createGraphics()?.apply { - drawImage(bufferImage, 0, 0, null) + drawImage(flippedImage, 0, 0, null) dispose() } } + private fun renderSoftwareRaster() { gameImage?.createGraphics()?.apply { SoftwareRaster.frameBuffer.draw(this) From 8b89a2bb8c68a712fb61c7df707ed8342541c975 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sun, 27 Oct 2024 20:22:16 -0700 Subject: [PATCH 16/25] Faster transforms --- .../src/main/kotlin/KondoKit/plugin.kt | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index aa3c242..8ee2e9f 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -155,8 +155,15 @@ class plugin : Plugin() { class AltCanvas : Canvas() { private var gameImage: VolatileImage? = null + private var op: AffineTransformOp? = null + private var transform: AffineTransform? = null + + private var flippedImage: BufferedImage? = null // Only used in HD private var bufferImage = BufferedImage(FIXED_WIDTH, FIXED_HEIGHT, BufferedImage.TYPE_INT_BGR) + private var lastImageWidth = -1 + private var lastImageHeight = -1 + init { isFocusable = true requestFocusInWindow() @@ -225,16 +232,6 @@ class plugin : Plugin() { } } - private fun calculateDrawDimensions(image: VolatileImage): Pair { - val imageAspect = image.width.toDouble() / image.height.toDouble() - val panelAspect = width.toDouble() / height.toDouble() - return if (imageAspect > panelAspect) { - width to (width / imageAspect).toInt() - } else { - (height * imageAspect).toInt() to height - } - } - private fun relayMouseEvent(e: MouseEvent) { requestFocusInWindow() val scale = minOf(width.toDouble() / gameImage!!.width, height.toDouble() / gameImage!!.height) @@ -259,22 +256,32 @@ class plugin : Plugin() { private fun renderGlRaster() { val width = gameImage!!.width val height = gameImage!!.height - val pixelData = GlRenderer.pixelData - bufferImage.setRGB(0, 0, width, height, pixelData, 0, width) + bufferImage.setRGB(0, 0, width, height, GlRenderer.pixelData, 0, width) - val transform = AffineTransform.getScaleInstance(1.0, -1.0) - transform.translate(0.0, -height.toDouble()) - val op = AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR) - val flippedImage = op.filter(bufferImage, null) + // Check if dimensions have changed + if (width != lastImageWidth || height != lastImageHeight) { + // Initialize or update transform and operation + transform = AffineTransform.getScaleInstance(1.0, -1.0).apply { + translate(0.0, -height.toDouble()) + } + op = AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR) + flippedImage = BufferedImage(width, height, bufferImage.type) + lastImageWidth = width + lastImageHeight = height + } + + // Apply the transform operation + op!!.filter(bufferImage, flippedImage) + + // Draw the flipped image onto gameImage gameImage?.createGraphics()?.apply { drawImage(flippedImage, 0, 0, null) dispose() } } - private fun renderSoftwareRaster() { gameImage?.createGraphics()?.apply { SoftwareRaster.frameBuffer.draw(this) From c307db1e11f2744f57cff2d6e316b368f36c92a8 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sun, 27 Oct 2024 21:38:12 -0700 Subject: [PATCH 17/25] double buffering --- .../src/main/kotlin/KondoKit/plugin.kt | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 8ee2e9f..9e7f325 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -158,7 +158,7 @@ class plugin : Plugin() { private var op: AffineTransformOp? = null private var transform: AffineTransform? = null - private var flippedImage: BufferedImage? = null // Only used in HD + private var flippedImage: BufferedImage? = null private var bufferImage = BufferedImage(FIXED_WIDTH, FIXED_HEIGHT, BufferedImage.TYPE_INT_BGR) private var lastImageWidth = -1 @@ -190,6 +190,7 @@ class plugin : Plugin() { override fun addNotify() { super.addNotify() + createBufferStrategy(2) // Double-buffering validateGameImage() } @@ -218,17 +219,23 @@ class plugin : Plugin() { } } - override fun paint(g: Graphics) { - val g2d = g as Graphics2D - g2d.color = Color.BLACK - g2d.fillRect(0, 0, width, height) - gameImage?.let { image -> - val scale = minOf(width.toDouble() / image.width, height.toDouble() / image.height) - val x = ((width - image.width * scale) / 2).toInt() - val y = ((height - image.height * scale) / 2).toInt() - g2d.drawImage(image, x, y, (image.width * scale).toInt(), (image.height * scale).toInt(), null) - Toolkit.getDefaultToolkit().sync() + override fun paint(g: Graphics) { + bufferStrategy?.let { strategy -> + val g2d = strategy.drawGraphics as? Graphics2D ?: return + + g2d.color = Color.BLACK + g2d.fillRect(0, 0, width, height) + + gameImage?.let { image -> + val scale = minOf(width.toDouble() / image.width, height.toDouble() / image.height) + val x = ((width - image.width * scale) / 2).toInt() + val y = ((height - image.height * scale) / 2).toInt() + g2d.drawImage(image, x, y, (image.width * scale).toInt(), (image.height * scale).toInt(), null) + } + + g2d.dispose() // Release the graphics context + strategy.show() // Display the buffer } } @@ -259,23 +266,18 @@ class plugin : Plugin() { bufferImage.setRGB(0, 0, width, height, GlRenderer.pixelData, 0, width) - // Check if dimensions have changed if (width != lastImageWidth || height != lastImageHeight) { - // Initialize or update transform and operation transform = AffineTransform.getScaleInstance(1.0, -1.0).apply { translate(0.0, -height.toDouble()) } op = AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR) flippedImage = BufferedImage(width, height, bufferImage.type) - lastImageWidth = width lastImageHeight = height } - // Apply the transform operation op!!.filter(bufferImage, flippedImage) - // Draw the flipped image onto gameImage gameImage?.createGraphics()?.apply { drawImage(flippedImage, 0, 0, null) dispose() From 07f4dc9349fba9112b1bca66256bc58295b728c3 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Mon, 28 Oct 2024 00:03:43 -0700 Subject: [PATCH 18/25] mostly working alt canvas --- .../src/main/kotlin/KondoKit/plugin.kt | 231 ++++++++++-------- 1 file changed, 135 insertions(+), 96 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 9e7f325..f6ab697 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -93,6 +93,9 @@ class plugin : Plugin() { "perfectly snapped to the edge of the game due to window chrome you can update this to fix it") var uiOffset = 0 + @Exposed("Stretched/Scaled Fixed Mode Support") + var useAltCanvas = false + private const val FIXED_WIDTH = 765 private const val FIXED_HEIGHT = 503 private const val NAVBAR_WIDTH = 30 @@ -113,6 +116,7 @@ class plugin : Plugin() { private var initialized = false private var lastClickTime = 0L private var lastUIOffset = 0 + private var themeName = "RUNELITE" private const val HIDDEN_VIEW = "HIDDEN" private var altCanvas: AltCanvas? = null private val drawActions = mutableListOf<() -> Unit>() @@ -292,27 +296,22 @@ class plugin : Plugin() { } } - private fun createAltCanvas(): AltCanvas { - return AltCanvas().apply { - preferredSize = Dimension(FIXED_WIDTH, FIXED_HEIGHT) - } - } - override fun Init() { // Disable Font AA System.setProperty("sun.java2d.opengl", "false") System.setProperty("awt.useSystemAAFontSettings", "off") System.setProperty("swing.aatext", "false") - val frame: Frame? = GameShell.frame + } + + private fun InitAltCanvas(){ if (frame != null) { - frame.layout = BorderLayout() - // Create the AltCanvas and add it to the main frame - altCanvas = createAltCanvas() + altCanvas = AltCanvas().apply { + preferredSize = Dimension(FIXED_WIDTH, FIXED_HEIGHT) + } altCanvas?.let { frame.add(it) } - // Use BorderLayout for better layout control - frame.setComponentZOrder(altCanvas, 0) - frame.setComponentZOrder(canvas, 1) + moveAltCanvasToFront() + frame.setComponentZOrder(rightPanelWrapper, 2) } } @@ -325,9 +324,15 @@ class plugin : Plugin() { if (frame.width < FIXED_WIDTH + currentScrollPaneWidth + uiOffset) { frame.setSize(FIXED_WIDTH + currentScrollPaneWidth + uiOffset, frame.height) } - canvas.setLocation(0,0) val difference = frame.width - (uiOffset + currentScrollPaneWidth) - altCanvas?.size = Dimension(difference, frame.height - 30) + if(useAltCanvas){ + GameShell.leftMargin = 0 + canvas.setLocation(0,canvas.y) + altCanvas?.size = Dimension(difference, frame.height - canvas.y) + } else { + GameShell.leftMargin = difference / 2 + canvas.setLocation(GameShell.leftMargin - (FIXED_WIDTH/2), canvas.y) + } } WindowMode.RESIZABLE -> { GameShell.canvasWidth = frame.width - (currentScrollPaneWidth + uiOffset) @@ -353,6 +358,15 @@ class plugin : Plugin() { LootTrackerView.gePriceMap = LootTrackerView.loadGEPrices() StoreData("kondoLaunchMinimized", launchMinimized) StoreData("kondoUIOffset", uiOffset) + StoreData("kondoScaleFixed", useAltCanvas) + if(altCanvas == null && useAltCanvas){ + InitAltCanvas() + UpdateDisplaySettings() + } else if(altCanvas != null && !useAltCanvas){ + frame.remove(altCanvas) + altCanvas = null + UpdateDisplaySettings() + } if(lastUIOffset != uiOffset){ UpdateDisplaySettings() reloadInterfaces = true @@ -472,99 +486,60 @@ class plugin : Plugin() { if (!initialized) return if(GameShell.fullScreenFrame != null) { DisplayMode.setWindowMode(true, 0, FIXED_WIDTH, FIXED_HEIGHT) - showAlert("Fullscreen is not supported by KondoKit. Disable the plugin", + showAlert("Fullscreen is not supported by KondoKit. Disable the plugin first.", "Error", JOptionPane.INFORMATION_MESSAGE ) - return; + return } + if(!useAltCanvas) return if(GetWindowMode() == WindowMode.RESIZABLE){ - frame.setComponentZOrder(altCanvas, 1) - frame.setComponentZOrder(canvas, 0) + moveAltCanvasToFront() } else { - frame.setComponentZOrder(altCanvas, 0) - frame.setComponentZOrder(canvas, 1) + moveCanvasToFront() } altCanvas?.updateGameImage() // Update the game image as needed } + private fun moveAltCanvasToFront(){ + if(altCanvas == null) { + println("WARNING: altcanvas is null") + return + } + frame.setComponentZOrder(altCanvas, 1) + frame.setComponentZOrder(canvas, 0) + } + + private fun moveCanvasToFront(){ + if(altCanvas == null) { + println("WARNING: altcanvas is null") + return + } + frame.setComponentZOrder(altCanvas, 0) + frame.setComponentZOrder(canvas, 1) + } + + private fun restoreSettings(){ + themeName = (GetData("kondoTheme") as? String) ?: "RUNELITE" + useLiveGEPrices = (GetData("kondoUseRemoteGE") as? Boolean) ?: true + playerXPMultiplier = (GetData("kondoPlayerXPMultiplier") as? Int) ?: 5 + val osName = System.getProperty("os.name").toLowerCase() + uiOffset = (GetData("kondoUIOffset") as? Int) ?: if (osName.contains("win")) 16 else 0 + launchMinimized = (GetData("kondoLaunchMinimized") as? Boolean) ?: false + useAltCanvas = (GetData("kondoScaleFixed") as? Boolean) ?: false + } + private fun initKondoUI(){ DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2) if(!allSpritesLoaded()) return; val frame: Frame? = GameShell.frame if (frame != null) { - + restoreSettings() loadFont() - val themeIndex = (GetData("kondoTheme") as? String) ?: "RUNELITE" - theme = ThemeType.valueOf(themeIndex) + theme = ThemeType.valueOf(themeName) applyTheme(getTheme(theme)) appliedTheme = theme - - try { - UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel") - - // Modify the UI properties to match theme - UIManager.put("control", VIEW_BACKGROUND_COLOR) - UIManager.put("info", VIEW_BACKGROUND_COLOR) - UIManager.put("nimbusBase", WIDGET_COLOR) - UIManager.put("nimbusBlueGrey", TITLE_BAR_COLOR) - - UIManager.put("nimbusDisabledText", primaryColor) - UIManager.put("nimbusSelectedText", secondaryColor) - UIManager.put("text", secondaryColor) - - UIManager.put("nimbusFocus", TITLE_BAR_COLOR) - UIManager.put("nimbusInfoBlue", POPUP_BACKGROUND) - UIManager.put("nimbusLightBackground", WIDGET_COLOR) - UIManager.put("nimbusSelectionBackground", PROGRESS_BAR_FILL) - - UIManager.put("Button.background", WIDGET_COLOR) - UIManager.put("Button.foreground", secondaryColor) - - UIManager.put("CheckBox.background", VIEW_BACKGROUND_COLOR) - UIManager.put("CheckBox.foreground", secondaryColor) - UIManager.put("CheckBox.icon", UIManager.getIcon("CheckBox.icon")) - - UIManager.put("ComboBox.background", WIDGET_COLOR) - UIManager.put("ComboBox.foreground", secondaryColor) - UIManager.put("ComboBox.selectionBackground", PROGRESS_BAR_FILL) - UIManager.put("ComboBox.selectionForeground", primaryColor) - UIManager.put("ComboBox.buttonBackground", WIDGET_COLOR) - - UIManager.put("Spinner.background", WIDGET_COLOR) - UIManager.put("Spinner.foreground", secondaryColor) - UIManager.put("Spinner.border", BorderFactory.createLineBorder(TITLE_BAR_COLOR)) - - UIManager.put("TextField.background", WIDGET_COLOR) - UIManager.put("TextField.foreground", secondaryColor) - UIManager.put("TextField.caretForeground", secondaryColor) - UIManager.put("TextField.border", BorderFactory.createLineBorder(TITLE_BAR_COLOR)) - - UIManager.put("ScrollBar.thumb", WIDGET_COLOR) - UIManager.put("ScrollBar.track", VIEW_BACKGROUND_COLOR) - UIManager.put("ScrollBar.thumbHighlight", TITLE_BAR_COLOR) - - UIManager.put("ProgressBar.foreground", PROGRESS_BAR_FILL) - UIManager.put("ProgressBar.background", WIDGET_COLOR) - UIManager.put("ProgressBar.border", BorderFactory.createLineBorder(TITLE_BAR_COLOR)) - - UIManager.put("ToolTip.background", VIEW_BACKGROUND_COLOR) - UIManager.put("ToolTip.foreground", secondaryColor) - UIManager.put("ToolTip.border", BorderFactory.createLineBorder(TITLE_BAR_COLOR)) - - // Update component tree UI to apply the new theme - SwingUtilities.updateComponentTreeUI(GameShell.frame) - GameShell.frame.background = Color.BLACK - } catch (e : Exception) { - e.printStackTrace() - } - - // Restore saved values - useLiveGEPrices = (GetData("kondoUseRemoteGE") as? Boolean) ?: true - playerXPMultiplier = (GetData("kondoPlayerXPMultiplier") as? Int) ?: 5 - val osName = System.getProperty("os.name").toLowerCase() - uiOffset = (GetData("kondoUIOffset") as? Int) ?: if (osName.contains("win")) 16 else 0 - launchMinimized = (GetData("kondoLaunchMinimized") as? Boolean) ?: false + configureLookAndFeel() cardLayout = CardLayout() mainContentPanel = JPanel(cardLayout).apply { @@ -596,7 +571,7 @@ class plugin : Plugin() { navPanel.add(createNavButton(LOOT_ICON, LootTrackerView.VIEW_NAME)) navPanel.add(createNavButton(WRENCH_ICON, ReflectiveEditorView.VIEW_NAME)) - var rightPanel = Panel(BorderLayout()).apply { + val rightPanel = Panel(BorderLayout()).apply { add(mainContentPanel, BorderLayout.CENTER) add(navPanel, BorderLayout.EAST) } @@ -604,7 +579,7 @@ class plugin : Plugin() { rightPanelWrapper = JScrollPane(rightPanel).apply { preferredSize = Dimension(NAVBAR_WIDTH + MAIN_CONTENT_WIDTH, frame.height) background = VIEW_BACKGROUND_COLOR - border = BorderFactory.createEmptyBorder() // Removes the border completely + border = BorderFactory.createEmptyBorder() horizontalScrollBarPolicy = JScrollPane.HORIZONTAL_SCROLLBAR_NEVER verticalScrollBarPolicy = JScrollPane.VERTICAL_SCROLLBAR_NEVER } @@ -612,13 +587,16 @@ class plugin : Plugin() { frame.layout = BorderLayout() rightPanelWrapper?.let { frame.add(it, BorderLayout.EAST) - frame.setComponentZOrder(it, 2) } - if(!launchMinimized){ - setActiveView(XPTrackerView.VIEW_NAME) - } else { + if(launchMinimized){ setActiveView(HIDDEN_VIEW) + } else { + setActiveView(XPTrackerView.VIEW_NAME) + } + if(useAltCanvas) { + InitAltCanvas() + UpdateDisplaySettings() } initialized = true pluginsReloaded = true @@ -761,6 +739,67 @@ class plugin : Plugin() { return panelButton } + private fun configureLookAndFeel(){ + try { + UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel") + + // Modify the UI properties to match theme + UIManager.put("control", VIEW_BACKGROUND_COLOR) + UIManager.put("info", VIEW_BACKGROUND_COLOR) + UIManager.put("nimbusBase", WIDGET_COLOR) + UIManager.put("nimbusBlueGrey", TITLE_BAR_COLOR) + + UIManager.put("nimbusDisabledText", primaryColor) + UIManager.put("nimbusSelectedText", secondaryColor) + UIManager.put("text", secondaryColor) + + UIManager.put("nimbusFocus", TITLE_BAR_COLOR) + UIManager.put("nimbusInfoBlue", POPUP_BACKGROUND) + UIManager.put("nimbusLightBackground", WIDGET_COLOR) + UIManager.put("nimbusSelectionBackground", PROGRESS_BAR_FILL) + + UIManager.put("Button.background", WIDGET_COLOR) + UIManager.put("Button.foreground", secondaryColor) + + UIManager.put("CheckBox.background", VIEW_BACKGROUND_COLOR) + UIManager.put("CheckBox.foreground", secondaryColor) + UIManager.put("CheckBox.icon", UIManager.getIcon("CheckBox.icon")) + + UIManager.put("ComboBox.background", WIDGET_COLOR) + UIManager.put("ComboBox.foreground", secondaryColor) + UIManager.put("ComboBox.selectionBackground", PROGRESS_BAR_FILL) + UIManager.put("ComboBox.selectionForeground", primaryColor) + UIManager.put("ComboBox.buttonBackground", WIDGET_COLOR) + + UIManager.put("Spinner.background", WIDGET_COLOR) + UIManager.put("Spinner.foreground", secondaryColor) + UIManager.put("Spinner.border", BorderFactory.createLineBorder(TITLE_BAR_COLOR)) + + UIManager.put("TextField.background", WIDGET_COLOR) + UIManager.put("TextField.foreground", secondaryColor) + UIManager.put("TextField.caretForeground", secondaryColor) + UIManager.put("TextField.border", BorderFactory.createLineBorder(TITLE_BAR_COLOR)) + + UIManager.put("ScrollBar.thumb", WIDGET_COLOR) + UIManager.put("ScrollBar.track", VIEW_BACKGROUND_COLOR) + UIManager.put("ScrollBar.thumbHighlight", TITLE_BAR_COLOR) + + UIManager.put("ProgressBar.foreground", PROGRESS_BAR_FILL) + UIManager.put("ProgressBar.background", WIDGET_COLOR) + UIManager.put("ProgressBar.border", BorderFactory.createLineBorder(TITLE_BAR_COLOR)) + + UIManager.put("ToolTip.background", VIEW_BACKGROUND_COLOR) + UIManager.put("ToolTip.foreground", secondaryColor) + UIManager.put("ToolTip.border", BorderFactory.createLineBorder(TITLE_BAR_COLOR)) + + // Update component tree UI to apply the new theme + SwingUtilities.updateComponentTreeUI(frame) + frame.background = Color.BLACK + } catch (e : Exception) { + e.printStackTrace() + } + } + fun loadFont(): Font? { val fontStream = plugin::class.java.getResourceAsStream("res/runescape_small.ttf") From c24df5ab46e53b912075a0ddabc51c078a512357 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Mon, 28 Oct 2024 07:18:08 -0700 Subject: [PATCH 19/25] cleanup files --- .../src/main/kotlin/KondoKit/AltCanvas.kt | 153 +++++++++++++++++ .../src/main/kotlin/KondoKit/plugin.kt | 161 +----------------- 2 files changed, 162 insertions(+), 152 deletions(-) create mode 100644 plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt diff --git a/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt b/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt new file mode 100644 index 0000000..cf3279d --- /dev/null +++ b/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt @@ -0,0 +1,153 @@ +package KondoKit + +import KondoKit.plugin.Companion.FIXED_HEIGHT +import KondoKit.plugin.Companion.FIXED_WIDTH +import plugin.api.API.IsHD +import rt4.GameShell.canvas +import rt4.GlRenderer +import rt4.SoftwareRaster +import java.awt.* +import java.awt.event.* +import java.awt.geom.AffineTransform +import java.awt.image.AffineTransformOp +import java.awt.image.BufferedImage +import java.awt.image.VolatileImage + +class AltCanvas : Canvas() { + private var gameImage: VolatileImage? = null + private var op: AffineTransformOp? = null + private var transform: AffineTransform? = null + + private var flippedImage: BufferedImage? = null + private var bufferImage = BufferedImage(FIXED_WIDTH, FIXED_HEIGHT, BufferedImage.TYPE_INT_BGR) + + private var lastImageWidth = -1 + private var lastImageHeight = -1 + + init { + isFocusable = true + requestFocusInWindow() + + addMouseListener(object : MouseAdapter() { + override fun mousePressed(e: MouseEvent) = relayMouseEvent(e) + override fun mouseReleased(e: MouseEvent) = relayMouseEvent(e) + override fun mouseClicked(e: MouseEvent) = relayMouseEvent(e) + }) + + addMouseMotionListener(object : MouseMotionAdapter() { + override fun mouseMoved(e: MouseEvent) = relayMouseEvent(e) + override fun mouseDragged(e: MouseEvent) = relayMouseEvent(e) + }) + + addKeyListener(object : KeyAdapter() { + override fun keyPressed(e: KeyEvent) = relayKeyEvent(e) { it.keyPressed(e) } + override fun keyReleased(e: KeyEvent) = relayKeyEvent(e) { it.keyReleased(e) } + override fun keyTyped(e: KeyEvent) = relayKeyEvent(e) { it.keyTyped(e) } + }) + } + + override fun update(g: Graphics) = paint(g) + + override fun addNotify() { + super.addNotify() + createBufferStrategy(2) // Double-buffering + validateGameImage() + } + + private fun validateGameImage() { + val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration + gameImage?.let { + when (it.validate(gc)) { + VolatileImage.IMAGE_INCOMPATIBLE -> createGameImage(gc) + VolatileImage.IMAGE_RESTORED -> renderGameImage() + } + } ?: createGameImage(gc) + } + + private fun createGameImage(gc: GraphicsConfiguration) { + gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) + renderGameImage() + } + + private fun renderGameImage() { + gameImage?.createGraphics()?.apply { + color = Color.DARK_GRAY + fillRect(0, 0, gameImage!!.width, gameImage!!.height) + color = Color.BLACK + drawString("KondoKit Scaled Fixed Canvas", 20, 20) + dispose() + } + } + + + override fun paint(g: Graphics) { + bufferStrategy?.let { strategy -> + val g2d = strategy.drawGraphics as? Graphics2D ?: return + + g2d.color = Color.BLACK + g2d.fillRect(0, 0, width, height) + + gameImage?.let { image -> + val scale = minOf(width.toDouble() / image.width, height.toDouble() / image.height) + val x = ((width - image.width * scale) / 2).toInt() + val y = ((height - image.height * scale) / 2).toInt() + g2d.drawImage(image, x, y, (image.width * scale).toInt(), (image.height * scale).toInt(), null) + } + + g2d.dispose() // Release the graphics context + strategy.show() // Display the buffer + } + } + + private fun relayMouseEvent(e: MouseEvent) { + requestFocusInWindow() + val scale = minOf(width.toDouble() / gameImage!!.width, height.toDouble() / gameImage!!.height) + val xOffset = ((width - gameImage!!.width * scale) / 2) + val yOffset = ((height - gameImage!!.height * scale) / 2) + + val adjustedX = ((e.x - xOffset) / scale).toInt().coerceIn(0, gameImage!!.width - 1) + val adjustedY = ((e.y - yOffset) / scale).toInt().coerceIn(0, gameImage!!.height - 1) + + canvas.dispatchEvent(MouseEvent(this, e.id, e.`when`, e.modifiersEx, adjustedX, adjustedY, e.clickCount, e.isPopupTrigger, e.button)) + } + + private fun relayKeyEvent(e: KeyEvent, action: (KeyListener) -> Unit) { + for (listener in canvas.keyListeners) action(listener) + } + + fun updateGameImage() { + if (IsHD()) renderGlRaster() else renderSoftwareRaster() + repaint() + } + + private fun renderGlRaster() { + val width = gameImage!!.width + val height = gameImage!!.height + + bufferImage.setRGB(0, 0, width, height, GlRenderer.pixelData, 0, width) + + if (width != lastImageWidth || height != lastImageHeight) { + transform = AffineTransform.getScaleInstance(1.0, -1.0).apply { + translate(0.0, -height.toDouble()) + } + op = AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR) + flippedImage = BufferedImage(width, height, bufferImage.type) + lastImageWidth = width + lastImageHeight = height + } + + op!!.filter(bufferImage, flippedImage) + + gameImage?.createGraphics()?.apply { + drawImage(flippedImage, 0, 0, null) + dispose() + } + } + + private fun renderSoftwareRaster() { + gameImage?.createGraphics()?.apply { + SoftwareRaster.frameBuffer.draw(this) + dispose() + } + } +} \ No newline at end of file diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index f6ab697..4e3167c 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -42,11 +42,9 @@ import rt4.client.js5Archive8 import rt4.client.mainLoadState import java.awt.* import java.awt.Font -import java.awt.event.* -import java.awt.geom.AffineTransform -import java.awt.image.AffineTransformOp -import java.awt.image.BufferedImage -import java.awt.image.VolatileImage +import java.awt.event.ActionListener +import java.awt.event.MouseAdapter +import java.awt.event.MouseEvent import javax.swing.* @@ -96,8 +94,8 @@ class plugin : Plugin() { @Exposed("Stretched/Scaled Fixed Mode Support") var useAltCanvas = false - private const val FIXED_WIDTH = 765 - private const val FIXED_HEIGHT = 503 + const val FIXED_WIDTH = 765 + const val FIXED_HEIGHT = 503 private const val NAVBAR_WIDTH = 30 private const val MAIN_CONTENT_WIDTH = 242 private const val WRENCH_ICON = 907 @@ -157,146 +155,6 @@ class plugin : Plugin() { lastLogin = Player.usernameInput.toString() } - class AltCanvas : Canvas() { - private var gameImage: VolatileImage? = null - private var op: AffineTransformOp? = null - private var transform: AffineTransform? = null - - private var flippedImage: BufferedImage? = null - private var bufferImage = BufferedImage(FIXED_WIDTH, FIXED_HEIGHT, BufferedImage.TYPE_INT_BGR) - - private var lastImageWidth = -1 - private var lastImageHeight = -1 - - init { - isFocusable = true - requestFocusInWindow() - - addMouseListener(object : MouseAdapter() { - override fun mousePressed(e: MouseEvent) = relayMouseEvent(e) - override fun mouseReleased(e: MouseEvent) = relayMouseEvent(e) - override fun mouseClicked(e: MouseEvent) = relayMouseEvent(e) - }) - - addMouseMotionListener(object : MouseMotionAdapter() { - override fun mouseMoved(e: MouseEvent) = relayMouseEvent(e) - override fun mouseDragged(e: MouseEvent) = relayMouseEvent(e) - }) - - addKeyListener(object : KeyAdapter() { - override fun keyPressed(e: KeyEvent) = relayKeyEvent(e) { it.keyPressed(e) } - override fun keyReleased(e: KeyEvent) = relayKeyEvent(e) { it.keyReleased(e) } - override fun keyTyped(e: KeyEvent) = relayKeyEvent(e) { it.keyTyped(e) } - }) - } - - override fun update(g: Graphics) = paint(g) - - override fun addNotify() { - super.addNotify() - createBufferStrategy(2) // Double-buffering - validateGameImage() - } - - private fun validateGameImage() { - val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration - gameImage?.let { - when (it.validate(gc)) { - VolatileImage.IMAGE_INCOMPATIBLE -> createGameImage(gc) - VolatileImage.IMAGE_RESTORED -> renderGameImage() - } - } ?: createGameImage(gc) - } - - private fun createGameImage(gc: GraphicsConfiguration) { - gameImage = gc.createCompatibleVolatileImage(FIXED_WIDTH, FIXED_HEIGHT, Transparency.OPAQUE) - renderGameImage() - } - - private fun renderGameImage() { - gameImage?.createGraphics()?.apply { - color = Color.RED - fillRect(0, 0, gameImage!!.width, gameImage!!.height) - color = Color.BLACK - drawString("Game Frame", 20, 20) - dispose() - } - } - - - override fun paint(g: Graphics) { - bufferStrategy?.let { strategy -> - val g2d = strategy.drawGraphics as? Graphics2D ?: return - - g2d.color = Color.BLACK - g2d.fillRect(0, 0, width, height) - - gameImage?.let { image -> - val scale = minOf(width.toDouble() / image.width, height.toDouble() / image.height) - val x = ((width - image.width * scale) / 2).toInt() - val y = ((height - image.height * scale) / 2).toInt() - g2d.drawImage(image, x, y, (image.width * scale).toInt(), (image.height * scale).toInt(), null) - } - - g2d.dispose() // Release the graphics context - strategy.show() // Display the buffer - } - } - - private fun relayMouseEvent(e: MouseEvent) { - requestFocusInWindow() - val scale = minOf(width.toDouble() / gameImage!!.width, height.toDouble() / gameImage!!.height) - val xOffset = ((width - gameImage!!.width * scale) / 2) - val yOffset = ((height - gameImage!!.height * scale) / 2) - - val adjustedX = ((e.x - xOffset) / scale).toInt().coerceIn(0, gameImage!!.width - 1) - val adjustedY = ((e.y - yOffset) / scale).toInt().coerceIn(0, gameImage!!.height - 1) - - canvas.dispatchEvent(MouseEvent(this, e.id, e.`when`, e.modifiersEx, adjustedX, adjustedY, e.clickCount, e.isPopupTrigger, e.button)) - } - - private fun relayKeyEvent(e: KeyEvent, action: (KeyListener) -> Unit) { - for (listener in canvas.keyListeners) action(listener) - } - - fun updateGameImage() { - if (IsHD()) renderGlRaster() else renderSoftwareRaster() - repaint() - } - - private fun renderGlRaster() { - val width = gameImage!!.width - val height = gameImage!!.height - - bufferImage.setRGB(0, 0, width, height, GlRenderer.pixelData, 0, width) - - if (width != lastImageWidth || height != lastImageHeight) { - transform = AffineTransform.getScaleInstance(1.0, -1.0).apply { - translate(0.0, -height.toDouble()) - } - op = AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR) - flippedImage = BufferedImage(width, height, bufferImage.type) - lastImageWidth = width - lastImageHeight = height - } - - op!!.filter(bufferImage, flippedImage) - - gameImage?.createGraphics()?.apply { - drawImage(flippedImage, 0, 0, null) - dispose() - } - } - - private fun renderSoftwareRaster() { - gameImage?.createGraphics()?.apply { - SoftwareRaster.frameBuffer.draw(this) - dispose() - } - } - } - - override fun Init() { // Disable Font AA System.setProperty("sun.java2d.opengl", "false") @@ -313,6 +171,7 @@ class plugin : Plugin() { moveAltCanvasToFront() frame.setComponentZOrder(rightPanelWrapper, 2) } + UpdateDisplaySettings() } private fun UpdateDisplaySettings() { @@ -328,9 +187,9 @@ class plugin : Plugin() { if(useAltCanvas){ GameShell.leftMargin = 0 canvas.setLocation(0,canvas.y) - altCanvas?.size = Dimension(difference, frame.height - canvas.y) + altCanvas?.size = Dimension(difference + uiOffset/2, frame.height - canvas.y) } else { - GameShell.leftMargin = difference / 2 + GameShell.leftMargin = (difference + uiOffset) / 2 canvas.setLocation(GameShell.leftMargin - (FIXED_WIDTH/2), canvas.y) } } @@ -361,7 +220,6 @@ class plugin : Plugin() { StoreData("kondoScaleFixed", useAltCanvas) if(altCanvas == null && useAltCanvas){ InitAltCanvas() - UpdateDisplaySettings() } else if(altCanvas != null && !useAltCanvas){ frame.remove(altCanvas) altCanvas = null @@ -535,7 +393,6 @@ class plugin : Plugin() { val frame: Frame? = GameShell.frame if (frame != null) { restoreSettings() - loadFont() theme = ThemeType.valueOf(themeName) applyTheme(getTheme(theme)) appliedTheme = theme @@ -596,7 +453,6 @@ class plugin : Plugin() { } if(useAltCanvas) { InitAltCanvas() - UpdateDisplaySettings() } initialized = true pluginsReloaded = true @@ -740,6 +596,7 @@ class plugin : Plugin() { } private fun configureLookAndFeel(){ + loadFont() try { UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel") From f2d4c175699b76f04309e31ccb47ccea9aec7c97 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Mon, 28 Oct 2024 10:53:23 -0700 Subject: [PATCH 20/25] Correct offsets --- .../main/kotlin/KondoKit/LootTrackerView.kt | 2 +- .../src/main/kotlin/KondoKit/plugin.kt | 64 ++++++++++++------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/LootTrackerView.kt b/plugin-playground/src/main/kotlin/KondoKit/LootTrackerView.kt index 3a0fc14..5f1a35a 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/LootTrackerView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/LootTrackerView.kt @@ -4,7 +4,6 @@ import KondoKit.Helpers.addMouseListenerToAll import KondoKit.Helpers.formatHtmlLabelText import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite import KondoKit.XPTrackerView.wrappedWidget -import KondoKit.plugin.Companion.IMAGE_SIZE import KondoKit.plugin.Companion.POPUP_BACKGROUND import KondoKit.plugin.Companion.POPUP_FOREGROUND import KondoKit.plugin.Companion.TITLE_BAR_COLOR @@ -351,6 +350,7 @@ object LootTrackerView { ?.apply { val newValue = (getClientProperty("val") as? Int ?: 0) + valueOfNewDrops.toInt() text = "${formatValue(newValue)} gp" + foreground = primaryColor putClientProperty("val", newValue) revalidate() if(focusedView == VIEW_NAME) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 4e3167c..fc34967 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -92,7 +92,7 @@ class plugin : Plugin() { var uiOffset = 0 @Exposed("Stretched/Scaled Fixed Mode Support") - var useAltCanvas = false + var useScaledFixed = false const val FIXED_WIDTH = 765 const val FIXED_HEIGHT = 503 @@ -162,7 +162,7 @@ class plugin : Plugin() { System.setProperty("swing.aatext", "false") } - private fun InitAltCanvas(){ + private fun initAltCanvas(){ if (frame != null) { altCanvas = AltCanvas().apply { preferredSize = Dimension(FIXED_WIDTH, FIXED_HEIGHT) @@ -178,27 +178,36 @@ class plugin : Plugin() { val mode = GetWindowMode() val currentScrollPaneWidth = if (mainContentPanel.isVisible) NAVBAR_WIDTH + MAIN_CONTENT_WIDTH else NAVBAR_WIDTH lastUIOffset = uiOffset + when (mode) { WindowMode.FIXED -> { if (frame.width < FIXED_WIDTH + currentScrollPaneWidth + uiOffset) { frame.setSize(FIXED_WIDTH + currentScrollPaneWidth + uiOffset, frame.height) } + val difference = frame.width - (uiOffset + currentScrollPaneWidth) - if(useAltCanvas){ + + if (useScaledFixed) { GameShell.leftMargin = 0 - canvas.setLocation(0,canvas.y) - altCanvas?.size = Dimension(difference + uiOffset/2, frame.height - canvas.y) + val canvasWidth = difference + uiOffset / 2 + val canvasHeight = frame.height - canvas.y // Restricting height to frame height + + altCanvas?.size = Dimension(canvasWidth, canvasHeight) + altCanvas?.setLocation(0, canvas.y) + canvas.setLocation(0, canvas.y) } else { GameShell.leftMargin = (difference + uiOffset) / 2 - canvas.setLocation(GameShell.leftMargin - (FIXED_WIDTH/2), canvas.y) + canvas.setLocation(GameShell.leftMargin - (FIXED_WIDTH / 2), canvas.y) } } + WindowMode.RESIZABLE -> { GameShell.canvasWidth = frame.width - (currentScrollPaneWidth + uiOffset) } } + rightPanelWrapper?.preferredSize = Dimension(currentScrollPaneWidth, frame.height) - rightPanelWrapper?.let { it.isDoubleBuffered = true } + rightPanelWrapper?.isDoubleBuffered = true rightPanelWrapper?.revalidate() rightPanelWrapper?.repaint() } @@ -217,13 +226,11 @@ class plugin : Plugin() { LootTrackerView.gePriceMap = LootTrackerView.loadGEPrices() StoreData("kondoLaunchMinimized", launchMinimized) StoreData("kondoUIOffset", uiOffset) - StoreData("kondoScaleFixed", useAltCanvas) - if(altCanvas == null && useAltCanvas){ - InitAltCanvas() - } else if(altCanvas != null && !useAltCanvas){ - frame.remove(altCanvas) - altCanvas = null - UpdateDisplaySettings() + StoreData("kondoScaledFixed", useScaledFixed) + if(altCanvas == null && useScaledFixed){ + initAltCanvas() + } else if(altCanvas != null && !useScaledFixed){ + destroyAltCanvas() } if(lastUIOffset != uiOffset){ UpdateDisplaySettings() @@ -231,6 +238,13 @@ class plugin : Plugin() { } } + private fun destroyAltCanvas(){ + moveCanvasToFront() + frame.remove(altCanvas) + altCanvas = null + UpdateDisplaySettings() + } + override fun OnMiniMenuCreate(currentEntries: Array?) { if (currentEntries != null) { for ((index, entry) in currentEntries.withIndex()) { @@ -350,8 +364,8 @@ class plugin : Plugin() { ) return } - if(!useAltCanvas) return - if(GetWindowMode() == WindowMode.RESIZABLE){ + if(!useScaledFixed) return + if(GetWindowMode() == WindowMode.FIXED){ moveAltCanvasToFront() } else { moveCanvasToFront() @@ -364,8 +378,10 @@ class plugin : Plugin() { println("WARNING: altcanvas is null") return } + frame.setComponentZOrder(canvas, 2) frame.setComponentZOrder(altCanvas, 1) - frame.setComponentZOrder(canvas, 0) + frame.setComponentZOrder(rightPanelWrapper, 0) + } private fun moveCanvasToFront(){ @@ -373,8 +389,9 @@ class plugin : Plugin() { println("WARNING: altcanvas is null") return } - frame.setComponentZOrder(altCanvas, 0) + frame.setComponentZOrder(altCanvas, 2) frame.setComponentZOrder(canvas, 1) + frame.setComponentZOrder(rightPanelWrapper, 0) } private fun restoreSettings(){ @@ -384,12 +401,12 @@ class plugin : Plugin() { val osName = System.getProperty("os.name").toLowerCase() uiOffset = (GetData("kondoUIOffset") as? Int) ?: if (osName.contains("win")) 16 else 0 launchMinimized = (GetData("kondoLaunchMinimized") as? Boolean) ?: false - useAltCanvas = (GetData("kondoScaleFixed") as? Boolean) ?: false + useScaledFixed = (GetData("kondoScaleFixed") as? Boolean) ?: false } private fun initKondoUI(){ DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2) - if(!allSpritesLoaded()) return; + if(!allSpritesLoaded()) return val frame: Frame? = GameShell.frame if (frame != null) { restoreSettings() @@ -451,8 +468,8 @@ class plugin : Plugin() { } else { setActiveView(XPTrackerView.VIEW_NAME) } - if(useAltCanvas) { - InitAltCanvas() + if(useScaledFixed) { + initAltCanvas() } initialized = true pluginsReloaded = true @@ -558,7 +575,7 @@ class plugin : Plugin() { maximumSize = buttonSize minimumSize = buttonSize background = WIDGET_COLOR - isOpaque = true // Ensure background is painted + isOpaque = true val gbc = GridBagConstraints().apply { anchor = GridBagConstraints.CENTER @@ -657,7 +674,6 @@ class plugin : Plugin() { } } - fun loadFont(): Font? { val fontStream = plugin::class.java.getResourceAsStream("res/runescape_small.ttf") return if (fontStream != null) { From 52d07d57958a8ecf1dcd5eaad952142497982797 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Mon, 28 Oct 2024 11:42:37 -0700 Subject: [PATCH 21/25] add mousewheel relay --- .../src/main/kotlin/KondoKit/AltCanvas.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt b/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt index cf3279d..319e7f5 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt @@ -44,6 +44,10 @@ class AltCanvas : Canvas() { override fun keyReleased(e: KeyEvent) = relayKeyEvent(e) { it.keyReleased(e) } override fun keyTyped(e: KeyEvent) = relayKeyEvent(e) { it.keyTyped(e) } }) + + addMouseWheelListener(object : MouseWheelListener { + override fun mouseWheelMoved(e: MouseWheelEvent) = relayMouseWheelEvent(e) + }) } override fun update(g: Graphics) = paint(g) @@ -115,6 +119,17 @@ class AltCanvas : Canvas() { for (listener in canvas.keyListeners) action(listener) } + private fun relayMouseWheelEvent(e: MouseWheelEvent) { + val scale = minOf(width.toDouble() / gameImage!!.width, height.toDouble() / gameImage!!.height) + val xOffset = ((width - gameImage!!.width * scale) / 2) + val yOffset = ((height - gameImage!!.height * scale) / 2) + + val adjustedX = ((e.x - xOffset) / scale).toInt().coerceIn(0, gameImage!!.width - 1) + val adjustedY = ((e.y - yOffset) / scale).toInt().coerceIn(0, gameImage!!.height - 1) + + canvas.dispatchEvent(MouseWheelEvent(this, e.id, e.`when`, e.modifiersEx, adjustedX, adjustedY, e.clickCount, e.isPopupTrigger, e.scrollType, e.scrollAmount, e.wheelRotation)) + } + fun updateGameImage() { if (IsHD()) renderGlRaster() else renderSoftwareRaster() repaint() From 1cca6611eeb8f7b909e6576cf24060f71324db33 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Mon, 28 Oct 2024 12:43:29 -0700 Subject: [PATCH 22/25] general cleanup --- .../src/main/kotlin/KondoKit/AltCanvas.kt | 12 +++--- .../src/main/kotlin/KondoKit/Helpers.kt | 12 ++---- .../src/main/kotlin/KondoKit/HiscoresView.kt | 14 +++---- .../main/kotlin/KondoKit/LootTrackerView.kt | 14 +++---- .../kotlin/KondoKit/ReflectiveEditorView.kt | 4 +- .../kotlin/KondoKit/SpriteToBufferedImage.kt | 12 +++--- .../src/main/kotlin/KondoKit/XPTable.kt | 6 +-- .../src/main/kotlin/KondoKit/plugin.kt | 37 ++++++++----------- 8 files changed, 46 insertions(+), 65 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt b/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt index 319e7f5..af5c01d 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt @@ -40,14 +40,12 @@ class AltCanvas : Canvas() { }) addKeyListener(object : KeyAdapter() { - override fun keyPressed(e: KeyEvent) = relayKeyEvent(e) { it.keyPressed(e) } - override fun keyReleased(e: KeyEvent) = relayKeyEvent(e) { it.keyReleased(e) } - override fun keyTyped(e: KeyEvent) = relayKeyEvent(e) { it.keyTyped(e) } + override fun keyPressed(e: KeyEvent) = relayKeyEvent { it.keyPressed(e) } + override fun keyReleased(e: KeyEvent) = relayKeyEvent { it.keyReleased(e) } + override fun keyTyped(e: KeyEvent) = relayKeyEvent { it.keyTyped(e) } }) - addMouseWheelListener(object : MouseWheelListener { - override fun mouseWheelMoved(e: MouseWheelEvent) = relayMouseWheelEvent(e) - }) + addMouseWheelListener(MouseWheelListener { e -> relayMouseWheelEvent(e) }) } override fun update(g: Graphics) = paint(g) @@ -115,7 +113,7 @@ class AltCanvas : Canvas() { canvas.dispatchEvent(MouseEvent(this, e.id, e.`when`, e.modifiersEx, adjustedX, adjustedY, e.clickCount, e.isPopupTrigger, e.button)) } - private fun relayKeyEvent(e: KeyEvent, action: (KeyListener) -> Unit) { + private fun relayKeyEvent(action: (KeyListener) -> Unit) { for (listener in canvas.keyListeners) action(listener) } diff --git a/plugin-playground/src/main/kotlin/KondoKit/Helpers.kt b/plugin-playground/src/main/kotlin/KondoKit/Helpers.kt index 67530e3..4f6e3c4 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/Helpers.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/Helpers.kt @@ -95,10 +95,8 @@ object Helpers { } - - fun convertToColor(value: String): Color { - val color = Color.decode(value) // Assumes value is in format "#RRGGBB" or "0xRRGGBB" - return color + private fun convertToColor(value: String): Color { + return Color.decode(value) } fun colorToHex(color: Color): String { @@ -134,11 +132,7 @@ object Helpers { class FieldNotifier(private val plugin: Any) { private val observers = mutableListOf() - fun addObserver(observer: FieldObserver) { - observers.add(observer) - } - - fun notifyFieldChange(field: Field, newValue: Any?) { + private fun notifyFieldChange(field: Field, newValue: Any?) { for (observer in observers) { observer.onFieldChange(field, newValue) } diff --git a/plugin-playground/src/main/kotlin/KondoKit/HiscoresView.kt b/plugin-playground/src/main/kotlin/KondoKit/HiscoresView.kt index f192098..0b48ab3 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/HiscoresView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/HiscoresView.kt @@ -75,8 +75,8 @@ object HiscoresView { private var cursorVisible: Boolean = true private val gson = Gson() - val bufferedImageSprite = getBufferedImageFromSprite(API.GetSprite(Constants.MAG_SPRITE)) - val imageCanvas = bufferedImageSprite.let { + private val bufferedImageSprite = getBufferedImageFromSprite(API.GetSprite(Constants.MAG_SPRITE)) + private val imageCanvas = bufferedImageSprite.let { ImageCanvas(it).apply { preferredSize = Constants.ICON_DIMENSION_SMALL size = preferredSize @@ -241,7 +241,7 @@ object HiscoresView { playerNameLabel?.revalidate() playerNameLabel?.repaint() - if(data == null) return; + if(data == null) return playerNameLabel?.removeAll() @@ -325,10 +325,6 @@ object HiscoresView { return Math.round((base + maxCombatType + summoningFactor) * 1000.0) / 1000.0 } - private fun showError(message: String) { - JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE) - } - private fun findComponentByName(container: Container, name: String): Component? { for (component in container.components) { if (name == component.name) { @@ -443,7 +439,7 @@ object HiscoresView { minimumSize = preferredSize } - val bufferedImageSprite = getBufferedImageFromSprite(API.GetSprite(Constants.LVL_BAR_SPRITE)); + val bufferedImageSprite = getBufferedImageFromSprite(API.GetSprite(Constants.LVL_BAR_SPRITE)) val totalLevelIcon = ImageCanvas(bufferedImageSprite).apply { fillColor = COLOR_BACKGROUND_DARK @@ -492,7 +488,7 @@ object HiscoresView { hiscorePanel.add(totalCombatPanel) hiscorePanel.add(Box.createVerticalStrut(10)) - hiScoreView = hiscorePanel; + hiScoreView = hiscorePanel } data class HiscoresResponse( diff --git a/plugin-playground/src/main/kotlin/KondoKit/LootTrackerView.kt b/plugin-playground/src/main/kotlin/KondoKit/LootTrackerView.kt index 5f1a35a..cfdb4a2 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/LootTrackerView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/LootTrackerView.kt @@ -32,15 +32,15 @@ import kotlin.math.ceil object LootTrackerView { private const val SNAPSHOT_LIFESPAN = 10 - const val BAG_ICON = 900; + const val BAG_ICON = 900 val npcDeathSnapshots = mutableMapOf() var gePriceMap = loadGEPrices() - const val VIEW_NAME = "LOOT_TRACKER_VIEW"; + const val VIEW_NAME = "LOOT_TRACKER_VIEW" private val lootItemPanels = mutableMapOf>() private val npcKillCounts = mutableMapOf() private var totalTrackerWidget: XPWidget? = null var lastConfirmedKillNpcId = -1 - var customToolTipWindow: JWindow? = null + private var customToolTipWindow: JWindow? = null var lootTrackerView: JPanel? = null fun loadGEPrices(): Map { @@ -283,7 +283,7 @@ object LootTrackerView { // Function to show the custom tooltip fun showCustomToolTip(location: Point, itemId: Int, quantity: Int, parentComponent: ImageCanvas) { - var itemDef = ObjTypeList.get(itemId) + val itemDef = ObjTypeList.get(itemId) val gePricePerItem = gePriceMap[itemDef.id.toString()]?.toInt() ?: 0 val totalGePrice = gePricePerItem * quantity val totalHaPrice = itemDef.cost * quantity @@ -382,7 +382,7 @@ object LootTrackerView { if (newDrops.isNotEmpty()) { val npcName = NpcTypeList.get(npcId).name - lastConfirmedKillNpcId = npcId; + lastConfirmedKillNpcId = npcId handleNewDrops(npcName.toString(), newDrops, lootTrackerView) toRemove.add(npcId) } else if (snapshot.age >= SNAPSHOT_LIFESPAN) { @@ -501,7 +501,7 @@ object LootTrackerView { return childFramePanel } - fun removeLootFrameMenu(toRemove: JPanel, npcName: String): JPopupMenu { + private fun removeLootFrameMenu(toRemove: JPanel, npcName: String): JPopupMenu { // Create a popup menu val popupMenu = JPopupMenu() val rFont = Font("RuneScape Small", Font.TRUETYPE_FONT, 16) @@ -538,7 +538,7 @@ object LootTrackerView { } - fun resetLootTrackerMenu(): JPopupMenu { + private fun resetLootTrackerMenu(): JPopupMenu { // Create a popup menu val popupMenu = JPopupMenu() val rFont = Font("RuneScape Small", Font.TRUETYPE_FONT, 16) diff --git a/plugin-playground/src/main/kotlin/KondoKit/ReflectiveEditorView.kt b/plugin-playground/src/main/kotlin/KondoKit/ReflectiveEditorView.kt index 60deccf..5b6cfd2 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/ReflectiveEditorView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/ReflectiveEditorView.kt @@ -30,7 +30,7 @@ import kotlin.math.ceil object ReflectiveEditorView { var reflectiveEditorView: JPanel? = null - val loadedPlugins: MutableList = mutableListOf() + private val loadedPlugins: MutableList = mutableListOf() const val VIEW_NAME = "REFLECTIVE_EDITOR_VIEW" fun createReflectiveEditorView() { val reflectiveEditorPanel = JPanel(BorderLayout()) @@ -266,7 +266,7 @@ object ReflectiveEditorView { } } else { - loadedPlugins.add(plugin.javaClass.`package`.name); + loadedPlugins.add(plugin.javaClass.`package`.name) } } diff --git a/plugin-playground/src/main/kotlin/KondoKit/SpriteToBufferedImage.kt b/plugin-playground/src/main/kotlin/KondoKit/SpriteToBufferedImage.kt index f955f95..0258838 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/SpriteToBufferedImage.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/SpriteToBufferedImage.kt @@ -69,7 +69,7 @@ object SpriteToBufferedImage { * @param brightnessBoost A multiplier to boost the brightness of the image. * @return The BufferedImage created from the sprite. */ - fun convertToBufferedImage( + private fun convertToBufferedImage( sprite: BaseSprite, tint: Color? = null, grayscale: Boolean = false, @@ -88,7 +88,7 @@ object SpriteToBufferedImage { for (y in 0 until height) { for (x in 0 until width) { val index = pixels[y * width + x].toInt() and 0xFF - var color = palette[index] + val color = palette[index] // Apply grayscale or tint if provided val finalColor = if (grayscale) { @@ -109,7 +109,7 @@ object SpriteToBufferedImage { // Manually set pixels directly for (y in 0 until height) { for (x in 0 until width) { - var color = pixels[y * width + x] + val color = pixels[y * width + x] // Apply grayscale or tint if provided val finalColor = if (grayscale) { @@ -137,7 +137,7 @@ object SpriteToBufferedImage { * @param brightnessBoost A multiplier to boost the brightness of the image. * @return The tinted color. */ - fun applyTint(original: Color, tint: Color, brightnessBoost: Float): Color { + private fun applyTint(original: Color, tint: Color, brightnessBoost: Float): Color { val boostedColor = applyBrightness(original, brightnessBoost) val r = (boostedColor.red * tint.red / 255).coerceIn(0, 255) val g = (boostedColor.green * tint.green / 255).coerceIn(0, 255) @@ -152,7 +152,7 @@ object SpriteToBufferedImage { * @param factor The multiplier to boost the brightness. * @return The color with boosted brightness. */ - fun applyBrightness(original: Color, factor: Float): Color { + private fun applyBrightness(original: Color, factor: Float): Color { val r = (original.red * factor).coerceIn(0.0f, 255.0f).toInt() val g = (original.green * factor).coerceIn(0.0f, 255.0f).toInt() val b = (original.blue * factor).coerceIn(0.0f, 255.0f).toInt() @@ -166,7 +166,7 @@ object SpriteToBufferedImage { * @param brightnessBoost A multiplier to boost the brightness. * @return The grayscale version of the color with boosted brightness. */ - fun applyGrayscale(original: Color, brightnessBoost: Float): Color { + private fun applyGrayscale(original: Color, brightnessBoost: Float): Color { // Calculate the grayscale value using the luminosity method val grayValue = (0.3 * original.red + 0.59 * original.green + 0.11 * original.blue).toInt() val boostedGray = (grayValue * brightnessBoost).coerceIn(0.0f, 255.0f).toInt() diff --git a/plugin-playground/src/main/kotlin/KondoKit/XPTable.kt b/plugin-playground/src/main/kotlin/KondoKit/XPTable.kt index 38df208..78138fe 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/XPTable.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/XPTable.kt @@ -6,9 +6,9 @@ import rt4.Node object XPTable { - const val MAX_LEVEL = 99 - const val INVALID_LEVEL = -1 - const val SKILLS_XP_TABLE = 716 + private const val MAX_LEVEL = 99 + private const val INVALID_LEVEL = -1 + private const val SKILLS_XP_TABLE = 716 private var xpTable: MutableList = mutableListOf() diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index fc34967..9eeba19 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -107,7 +107,7 @@ class plugin : Plugin() { private var rightPanelWrapper: JScrollPane? = null private var accumulatedTime = 0L private var reloadInterfaces = false - private const val tickInterval = 600L + private const val TICK_INTERVAL = 600L private var pluginsReloaded = false private var loginScreen = 160 private var lastLogin = "" @@ -126,7 +126,7 @@ class plugin : Plugin() { } } - fun allSpritesLoaded() : Boolean { + private fun allSpritesLoaded() : Boolean { // Check all skill sprites try{ for (i in 0 until 24) { @@ -171,10 +171,10 @@ class plugin : Plugin() { moveAltCanvasToFront() frame.setComponentZOrder(rightPanelWrapper, 2) } - UpdateDisplaySettings() + updateDisplaySettings() } - private fun UpdateDisplaySettings() { + private fun updateDisplaySettings() { val mode = GetWindowMode() val currentScrollPaneWidth = if (mainContentPanel.isVisible) NAVBAR_WIDTH + MAIN_CONTENT_WIDTH else NAVBAR_WIDTH lastUIOffset = uiOffset @@ -233,7 +233,7 @@ class plugin : Plugin() { destroyAltCanvas() } if(lastUIOffset != uiOffset){ - UpdateDisplaySettings() + updateDisplaySettings() reloadInterfaces = true } } @@ -242,7 +242,7 @@ class plugin : Plugin() { moveCanvasToFront() frame.remove(altCanvas) altCanvas = null - UpdateDisplaySettings() + updateDisplaySettings() } override fun OnMiniMenuCreate(currentEntries: Array?) { @@ -278,10 +278,10 @@ class plugin : Plugin() { override fun OnPluginsReloaded(): Boolean { if (!initialized) return true - UpdateDisplaySettings() + updateDisplaySettings() frame.remove(rightPanelWrapper) frame.layout = BorderLayout() - frame.add(rightPanelWrapper, BorderLayout.EAST) + rightPanelWrapper?.let { frame.add(it, BorderLayout.EAST) } frame.revalidate() pluginsReloaded = true reloadInterfaces = true @@ -332,7 +332,7 @@ class plugin : Plugin() { } accumulatedTime += timeDelta - if (accumulatedTime >= tickInterval) { + if (accumulatedTime >= TICK_INTERVAL) { lootTrackerView?.let { onPostClientTick(it) } accumulatedTime = 0L } @@ -374,21 +374,14 @@ class plugin : Plugin() { } private fun moveAltCanvasToFront(){ - if(altCanvas == null) { - println("WARNING: altcanvas is null") - return - } + if(altCanvas == null) return frame.setComponentZOrder(canvas, 2) frame.setComponentZOrder(altCanvas, 1) frame.setComponentZOrder(rightPanelWrapper, 0) - } private fun moveCanvasToFront(){ - if(altCanvas == null) { - println("WARNING: altcanvas is null") - return - } + if(altCanvas == null) return frame.setComponentZOrder(altCanvas, 2) frame.setComponentZOrder(canvas, 1) frame.setComponentZOrder(rightPanelWrapper, 0) @@ -401,7 +394,7 @@ class plugin : Plugin() { val osName = System.getProperty("os.name").toLowerCase() uiOffset = (GetData("kondoUIOffset") as? Int) ?: if (osName.contains("win")) 16 else 0 launchMinimized = (GetData("kondoLaunchMinimized") as? Boolean) ?: false - useScaledFixed = (GetData("kondoScaleFixed") as? Boolean) ?: false + useScaledFixed = (GetData("kondoScaledFixed") as? Boolean) ?: false } private fun initKondoUI(){ @@ -517,7 +510,7 @@ class plugin : Plugin() { } reloadInterfaces = true - UpdateDisplaySettings() + updateDisplaySettings() // Revalidate and repaint necessary panels mainContentPanel.revalidate() @@ -674,7 +667,7 @@ class plugin : Plugin() { } } - fun loadFont(): Font? { + private fun loadFont(): Font? { val fontStream = plugin::class.java.getResourceAsStream("res/runescape_small.ttf") return if (fontStream != null) { try { @@ -696,7 +689,7 @@ class plugin : Plugin() { var focusedView: String = "" } - fun applyTheme(theme: Theme) { + private fun applyTheme(theme: Theme) { WIDGET_COLOR = theme.widgetColor TITLE_BAR_COLOR = theme.titleBarColor VIEW_BACKGROUND_COLOR = theme.viewBackgroundColor From cb9758f7d5c4d6e4643b8cb738f319545124381a Mon Sep 17 00:00:00 2001 From: downthecrop Date: Mon, 28 Oct 2024 16:22:40 -0700 Subject: [PATCH 23/25] Organize overrides to be together in the source --- .../src/main/kotlin/KondoKit/plugin.kt | 296 +++++++++--------- 1 file changed, 148 insertions(+), 148 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 9eeba19..c0de33a 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -126,24 +126,11 @@ class plugin : Plugin() { } } - private fun allSpritesLoaded() : Boolean { - // Check all skill sprites - try{ - for (i in 0 until 24) { - if(!js5Archive8.isFileReady(getSpriteId(i))){ - return false - } - } - val otherIcons = arrayOf(LVL_ICON, MAG_SPRITE, LOOT_ICON, WRENCH_ICON, COMBAT_LVL_SPRITE, BAG_ICON) - for (icon in otherIcons) { - if(!js5Archive8.isFileReady(icon)){ - return false - } - } - } catch (e : Exception){ - return false - } - return true + override fun Init() { + // Disable Font AA + System.setProperty("sun.java2d.opengl", "false") + System.setProperty("awt.useSystemAAFontSettings", "off") + System.setProperty("swing.aatext", "false") } override fun OnLogin() { @@ -155,96 +142,6 @@ class plugin : Plugin() { lastLogin = Player.usernameInput.toString() } - override fun Init() { - // Disable Font AA - System.setProperty("sun.java2d.opengl", "false") - System.setProperty("awt.useSystemAAFontSettings", "off") - System.setProperty("swing.aatext", "false") - } - - private fun initAltCanvas(){ - if (frame != null) { - altCanvas = AltCanvas().apply { - preferredSize = Dimension(FIXED_WIDTH, FIXED_HEIGHT) - } - altCanvas?.let { frame.add(it) } - moveAltCanvasToFront() - frame.setComponentZOrder(rightPanelWrapper, 2) - } - updateDisplaySettings() - } - - private fun updateDisplaySettings() { - val mode = GetWindowMode() - val currentScrollPaneWidth = if (mainContentPanel.isVisible) NAVBAR_WIDTH + MAIN_CONTENT_WIDTH else NAVBAR_WIDTH - lastUIOffset = uiOffset - - when (mode) { - WindowMode.FIXED -> { - if (frame.width < FIXED_WIDTH + currentScrollPaneWidth + uiOffset) { - frame.setSize(FIXED_WIDTH + currentScrollPaneWidth + uiOffset, frame.height) - } - - val difference = frame.width - (uiOffset + currentScrollPaneWidth) - - if (useScaledFixed) { - GameShell.leftMargin = 0 - val canvasWidth = difference + uiOffset / 2 - val canvasHeight = frame.height - canvas.y // Restricting height to frame height - - altCanvas?.size = Dimension(canvasWidth, canvasHeight) - altCanvas?.setLocation(0, canvas.y) - canvas.setLocation(0, canvas.y) - } else { - GameShell.leftMargin = (difference + uiOffset) / 2 - canvas.setLocation(GameShell.leftMargin - (FIXED_WIDTH / 2), canvas.y) - } - } - - WindowMode.RESIZABLE -> { - GameShell.canvasWidth = frame.width - (currentScrollPaneWidth + uiOffset) - } - } - - rightPanelWrapper?.preferredSize = Dimension(currentScrollPaneWidth, frame.height) - rightPanelWrapper?.isDoubleBuffered = true - rightPanelWrapper?.revalidate() - rightPanelWrapper?.repaint() - } - - fun OnKondoValueUpdated(){ - StoreData("kondoUseRemoteGE", useLiveGEPrices) - StoreData("kondoTheme", theme.toString()) - if(appliedTheme != theme) { - showAlert( - "KondoKit Theme changes require a relaunch.", - "KondoKit", - JOptionPane.INFORMATION_MESSAGE - ) - } - StoreData("kondoPlayerXPMultiplier", playerXPMultiplier) - LootTrackerView.gePriceMap = LootTrackerView.loadGEPrices() - StoreData("kondoLaunchMinimized", launchMinimized) - StoreData("kondoUIOffset", uiOffset) - StoreData("kondoScaledFixed", useScaledFixed) - if(altCanvas == null && useScaledFixed){ - initAltCanvas() - } else if(altCanvas != null && !useScaledFixed){ - destroyAltCanvas() - } - if(lastUIOffset != uiOffset){ - updateDisplaySettings() - reloadInterfaces = true - } - } - - private fun destroyAltCanvas(){ - moveCanvasToFront() - frame.remove(altCanvas) - altCanvas = null - updateDisplaySettings() - } - override fun OnMiniMenuCreate(currentEntries: Array?) { if (currentEntries != null) { for ((index, entry) in currentEntries.withIndex()) { @@ -265,17 +162,6 @@ class plugin : Plugin() { } } - private fun searchHiscore(username: String): Runnable { - return Runnable { - setActiveView(HiscoresView.VIEW_NAME) - val customSearchField = hiScoreView?.let { HiscoresView.CustomSearchField(it) } - - customSearchField?.searchPlayer(username) ?: run { - println("searchView is null or CustomSearchField creation failed.") - } - } - } - override fun OnPluginsReloaded(): Boolean { if (!initialized) return true updateDisplaySettings() @@ -373,6 +259,149 @@ class plugin : Plugin() { altCanvas?.updateGameImage() // Update the game image as needed } + override fun Update() { + + val widgets = xpWidgets.values + val totalXP = totalXPWidget + + widgets.forEach { xpWidget -> + val elapsedTime = (System.currentTimeMillis() - xpWidget.startTime) / 1000.0 / 60.0 / 60.0 + val xpPerHour = if (elapsedTime > 0) (xpWidget.totalXpGained / elapsedTime).toInt() else 0 + val formattedXpPerHour = formatNumber(xpPerHour) + xpWidget.xpPerHourLabel.text = + formatHtmlLabelText("XP /hr: ", primaryColor, formattedXpPerHour, secondaryColor) + xpWidget.container.repaint() + } + + totalXP?.let { totalXPWidget -> + val elapsedTime = (System.currentTimeMillis() - totalXPWidget.startTime) / 1000.0 / 60.0 / 60.0 + val totalXPPerHour = if (elapsedTime > 0) (totalXPWidget.totalXpGained / elapsedTime).toInt() else 0 + val formattedTotalXpPerHour = formatNumber(totalXPPerHour) + totalXPWidget.xpPerHourLabel.text = + formatHtmlLabelText("XP /hr: ", primaryColor, formattedTotalXpPerHour, secondaryColor) + totalXPWidget.container.repaint() + } + } + + override fun OnKillingBlowNPC(npcID: Int, x: Int, z: Int) { + val preDeathSnapshot = takeGroundSnapshot(Pair(x,z)) + npcDeathSnapshots[npcID] = LootTrackerView.GroundSnapshot(preDeathSnapshot, Pair(x, z), 0) + } + + private fun allSpritesLoaded() : Boolean { + // Check all skill sprites + try{ + for (i in 0 until 24) { + if(!js5Archive8.isFileReady(getSpriteId(i))){ + return false + } + } + val otherIcons = arrayOf(LVL_ICON, MAG_SPRITE, LOOT_ICON, WRENCH_ICON, COMBAT_LVL_SPRITE, BAG_ICON) + for (icon in otherIcons) { + if(!js5Archive8.isFileReady(icon)){ + return false + } + } + } catch (e : Exception){ + return false + } + return true + } + + private fun initAltCanvas(){ + if (frame != null) { + altCanvas = AltCanvas().apply { + preferredSize = Dimension(FIXED_WIDTH, FIXED_HEIGHT) + } + altCanvas?.let { frame.add(it) } + moveAltCanvasToFront() + frame.setComponentZOrder(rightPanelWrapper, 2) + } + updateDisplaySettings() + } + + private fun updateDisplaySettings() { + val mode = GetWindowMode() + val currentScrollPaneWidth = if (mainContentPanel.isVisible) NAVBAR_WIDTH + MAIN_CONTENT_WIDTH else NAVBAR_WIDTH + lastUIOffset = uiOffset + + when (mode) { + WindowMode.FIXED -> { + if (frame.width < FIXED_WIDTH + currentScrollPaneWidth + uiOffset) { + frame.setSize(FIXED_WIDTH + currentScrollPaneWidth + uiOffset, frame.height) + } + + val difference = frame.width - (uiOffset + currentScrollPaneWidth) + + if (useScaledFixed) { + GameShell.leftMargin = 0 + val canvasWidth = difference + uiOffset / 2 + val canvasHeight = frame.height - canvas.y // Restricting height to frame height + + altCanvas?.size = Dimension(canvasWidth, canvasHeight) + altCanvas?.setLocation(0, canvas.y) + canvas.setLocation(0, canvas.y) + } else { + GameShell.leftMargin = (difference + uiOffset) / 2 + canvas.setLocation(GameShell.leftMargin - (FIXED_WIDTH / 2), canvas.y) + } + } + + WindowMode.RESIZABLE -> { + GameShell.canvasWidth = frame.width - (currentScrollPaneWidth + uiOffset) + } + } + + rightPanelWrapper?.preferredSize = Dimension(currentScrollPaneWidth, frame.height) + rightPanelWrapper?.isDoubleBuffered = true + rightPanelWrapper?.revalidate() + rightPanelWrapper?.repaint() + } + + fun OnKondoValueUpdated(){ + StoreData("kondoUseRemoteGE", useLiveGEPrices) + StoreData("kondoTheme", theme.toString()) + if(appliedTheme != theme) { + showAlert( + "KondoKit Theme changes require a relaunch.", + "KondoKit", + JOptionPane.INFORMATION_MESSAGE + ) + } + StoreData("kondoPlayerXPMultiplier", playerXPMultiplier) + LootTrackerView.gePriceMap = LootTrackerView.loadGEPrices() + StoreData("kondoLaunchMinimized", launchMinimized) + StoreData("kondoUIOffset", uiOffset) + StoreData("kondoScaledFixed", useScaledFixed) + if(altCanvas == null && useScaledFixed){ + initAltCanvas() + } else if(altCanvas != null && !useScaledFixed){ + destroyAltCanvas() + } + if(lastUIOffset != uiOffset){ + updateDisplaySettings() + reloadInterfaces = true + } + } + + private fun destroyAltCanvas(){ + moveCanvasToFront() + frame.remove(altCanvas) + altCanvas = null + updateDisplaySettings() + } + + private fun searchHiscore(username: String): Runnable { + return Runnable { + setActiveView(HiscoresView.VIEW_NAME) + val customSearchField = hiScoreView?.let { HiscoresView.CustomSearchField(it) } + + customSearchField?.searchPlayer(username) ?: run { + println("searchView is null or CustomSearchField creation failed.") + } + } + } + private fun moveAltCanvasToFront(){ if(altCanvas == null) return frame.setComponentZOrder(canvas, 2) @@ -469,35 +498,6 @@ class plugin : Plugin() { } } - override fun Update() { - - val widgets = xpWidgets.values - val totalXP = totalXPWidget - - widgets.forEach { xpWidget -> - val elapsedTime = (System.currentTimeMillis() - xpWidget.startTime) / 1000.0 / 60.0 / 60.0 - val xpPerHour = if (elapsedTime > 0) (xpWidget.totalXpGained / elapsedTime).toInt() else 0 - val formattedXpPerHour = formatNumber(xpPerHour) - xpWidget.xpPerHourLabel.text = - formatHtmlLabelText("XP /hr: ", primaryColor, formattedXpPerHour, secondaryColor) - xpWidget.container.repaint() - } - - totalXP?.let { totalXPWidget -> - val elapsedTime = (System.currentTimeMillis() - totalXPWidget.startTime) / 1000.0 / 60.0 / 60.0 - val totalXPPerHour = if (elapsedTime > 0) (totalXPWidget.totalXpGained / elapsedTime).toInt() else 0 - val formattedTotalXpPerHour = formatNumber(totalXPPerHour) - totalXPWidget.xpPerHourLabel.text = - formatHtmlLabelText("XP /hr: ", primaryColor, formattedTotalXpPerHour, secondaryColor) - totalXPWidget.container.repaint() - } - } - - override fun OnKillingBlowNPC(npcID: Int, x: Int, z: Int) { - val preDeathSnapshot = takeGroundSnapshot(Pair(x,z)) - npcDeathSnapshots[npcID] = LootTrackerView.GroundSnapshot(preDeathSnapshot, Pair(x, z), 0) - } - private fun setActiveView(viewName: String) { // Handle the visibility of the main content panel if (viewName == HIDDEN_VIEW) { From cf5ccbf1acfec6c852146278cb9d0298c19a9776 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Mon, 28 Oct 2024 16:32:51 -0700 Subject: [PATCH 24/25] undo some testing changes --- client/src/main/java/plugin/PluginRepository.java | 6 +++--- client/src/main/java/rt4/GameShell.java | 6 ++---- client/src/main/java/rt4/GlRenderer.java | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/client/src/main/java/plugin/PluginRepository.java b/client/src/main/java/plugin/PluginRepository.java index 4225c8c..55faf80 100644 --- a/client/src/main/java/plugin/PluginRepository.java +++ b/client/src/main/java/plugin/PluginRepository.java @@ -70,7 +70,7 @@ public class PluginRepository { File pluginsDirectory = new File(GlobalJsonConfig.instance.pluginsFolder); if (!pluginsDirectory.exists()) { - //System.out.println("Skipping plugin initialization - " + pluginsDirectory.getAbsolutePath() + " does not exist."); + System.out.println("Skipping plugin initialization - " + pluginsDirectory.getAbsolutePath() + " does not exist."); return; } @@ -120,7 +120,7 @@ public class PluginRepository { } if (loadedPlugins.containsKey(info)) { - //System.out.println("Skipping reloading of plugin " + file.getName() + " as it already exists and has OnPluginsReloaded."); + System.out.println("Skipping reloading of plugin " + file.getName() + " as it already exists and has OnPluginsReloaded."); continue; } @@ -143,7 +143,7 @@ public class PluginRepository { loader.loadClass(file.getName() + "." + f.getName().replace(".class","")); } - //System.out.println("Successfully loaded plugin " + file.getName() + ", version " + info.version); + System.out.println("Successfully loaded plugin " + file.getName() + ", version " + info.version); } } catch (Exception e) { System.err.println("Unexpected exception during plugin initialization:"); diff --git a/client/src/main/java/rt4/GameShell.java b/client/src/main/java/rt4/GameShell.java index 68e6c32..80a799d 100644 --- a/client/src/main/java/rt4/GameShell.java +++ b/client/src/main/java/rt4/GameShell.java @@ -323,7 +323,6 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene @OriginalMember(owner = "client!rc", name = "b", descriptor = "(B)V") public final synchronized void addCanvas() { if (canvas != null) { - // Remove the old canvas if it exists canvas.removeFocusListener(this); canvas.getParent().remove(canvas); } @@ -514,10 +513,9 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene canvasScale = getCurrentDevice().getDefaultConfiguration().getDefaultTransform().getScaleX(); if (frame != null && fullScreenFrame == null) { @Pc(84) Insets insets = frame.getInsets(); - // TODO: Add a flag to ignore this. - //canvas.setLocation(insets.left + leftMargin, topMargin + insets.top); + canvas.setLocation(insets.left + leftMargin, topMargin + insets.top); } else { - //canvas.setLocation(leftMargin, topMargin); + canvas.setLocation(leftMargin, topMargin); } } this.mainRedraw(); diff --git a/client/src/main/java/rt4/GlRenderer.java b/client/src/main/java/rt4/GlRenderer.java index d644740..92e4564 100644 --- a/client/src/main/java/rt4/GlRenderer.java +++ b/client/src/main/java/rt4/GlRenderer.java @@ -73,7 +73,7 @@ public final class GlRenderer { private static int maxTextureCoords; @OriginalMember(owner = "client!tf", name = "E", descriptor = "Lgl!javax/media/opengl/GLDrawable;") - public static GLDrawable drawable; + private static GLDrawable drawable; @OriginalMember(owner = "client!tf", name = "H", descriptor = "Z") public static boolean arbVertexProgramSupported; From e05f5829d7f4654f13f711074242866a797c5b93 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Mon, 28 Oct 2024 16:38:33 -0700 Subject: [PATCH 25/25] Restore original Kondo Fixed mode handling --- plugin-playground/src/main/kotlin/KondoKit/plugin.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index c0de33a..f5073ac 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -342,8 +342,8 @@ class plugin : Plugin() { altCanvas?.setLocation(0, canvas.y) canvas.setLocation(0, canvas.y) } else { - GameShell.leftMargin = (difference + uiOffset) / 2 - canvas.setLocation(GameShell.leftMargin - (FIXED_WIDTH / 2), canvas.y) + val difference = frame.width - (FIXED_WIDTH + uiOffset + currentScrollPaneWidth) + GameShell.leftMargin = difference / 2 } }