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?) {