FIXED streched mode

This commit is contained in:
downthecrop 2024-10-24 12:03:16 -07:00
parent fce9b4eea7
commit 668345b81e
5 changed files with 191 additions and 8 deletions

View file

@ -13,6 +13,7 @@ import rt4.Tile;
*/ */
public abstract class Plugin { public abstract class Plugin {
long timeOfLastDraw; long timeOfLastDraw;
long timeOfLastLateDraw;
void _init() { void _init() {
Init(); Init();
@ -24,6 +25,12 @@ public abstract class Plugin {
timeOfLastDraw = nowTime; 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. * 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. * 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) {} 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 * Init() is called when the plugin is first loaded
*/ */

View file

@ -160,6 +160,11 @@ public class PluginRepository {
pluginsSnapshot.forEach(Plugin::_draw); pluginsSnapshot.forEach(Plugin::_draw);
} }
public static void LateDraw() {
List<Plugin> pluginsSnapshot = new ArrayList<>(loadedPlugins.values());
pluginsSnapshot.forEach(Plugin::_lateDraw);
}
public static void NPCOverheadDraw(Npc npc, int screenX, int screenY) { public static void NPCOverheadDraw(Npc npc, int screenX, int screenY) {
loadedPlugins.values().forEach((plugin) -> plugin.NPCOverheadDraw(npc, screenX, screenY)); loadedPlugins.values().forEach((plugin) -> plugin.NPCOverheadDraw(npc, screenX, screenY));
} }

View file

@ -12,7 +12,7 @@ import java.awt.*;
public abstract class FrameBuffer { public abstract class FrameBuffer {
@OriginalMember(owner = "client!vk", name = "e", descriptor = "[I") @OriginalMember(owner = "client!vk", name = "e", descriptor = "[I")
protected int[] pixels; public int[] pixels;
@OriginalMember(owner = "client!vk", name = "g", descriptor = "Ljava/awt/Image;") @OriginalMember(owner = "client!vk", name = "g", descriptor = "Ljava/awt/Image;")
protected Image image; protected Image image;

View file

@ -921,6 +921,7 @@ public final class client extends GameShell {
Preferences.safeMode = false; Preferences.safeMode = false;
Preferences.write(GameShell.signLink); Preferences.write(GameShell.signLink);
} }
PluginRepository.LateDraw();
} }
@OriginalMember(owner = "client!client", name = "c", descriptor = "(B)V") @OriginalMember(owner = "client!client", name = "c", descriptor = "(B)V")

View file

@ -35,16 +35,17 @@ import plugin.api.*
import plugin.api.API.* import plugin.api.API.*
import plugin.api.FontColor.fromColor import plugin.api.FontColor.fromColor
import rt4.GameShell import rt4.GameShell
import rt4.GameShell.canvas
import rt4.GameShell.frame import rt4.GameShell.frame
import rt4.GlRenderer import rt4.GlRenderer
import rt4.InterfaceList import rt4.InterfaceList
import rt4.Player import rt4.Player
import rt4.SoftwareRaster
import rt4.client.js5Archive8 import rt4.client.js5Archive8
import rt4.client.mainLoadState import rt4.client.mainLoadState
import java.awt.* import java.awt.*
import java.awt.event.ActionListener import java.awt.event.*
import java.awt.event.MouseAdapter import java.awt.image.BufferedImage
import java.awt.event.MouseEvent
import javax.swing.* import javax.swing.*
import javax.swing.plaf.nimbus.AbstractRegionPainter import javax.swing.plaf.nimbus.AbstractRegionPainter
@ -149,12 +150,157 @@ class plugin : Plugin() {
} }
lastLogin = Player.usernameInput.toString() 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() { override fun Init() {
// Disable Font AA // Disable Font AA
System.setProperty("sun.java2d.opengl", "false") System.setProperty("sun.java2d.opengl", "false")
System.setProperty("awt.useSystemAAFontSettings", "off") System.setProperty("awt.useSystemAAFontSettings", "off")
System.setProperty("swing.aatext", "false") 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() { private fun UpdateDisplaySettings() {
@ -166,9 +312,8 @@ class plugin : Plugin() {
if (frame.width < FIXED_WIDTH + currentScrollPaneWidth + uiOffset) { if (frame.width < FIXED_WIDTH + currentScrollPaneWidth + uiOffset) {
frame.setSize(FIXED_WIDTH + currentScrollPaneWidth + uiOffset, frame.height) frame.setSize(FIXED_WIDTH + currentScrollPaneWidth + uiOffset, frame.height)
} }
val difference = frame.width - (uiOffset + currentScrollPaneWidth)
val difference = frame.width - (FIXED_WIDTH + uiOffset + currentScrollPaneWidth) altCanvas?.size = Dimension(difference, frame.height - 30)
GameShell.leftMargin = difference / 2
} }
WindowMode.RESIZABLE -> { WindowMode.RESIZABLE -> {
GameShell.canvasWidth = frame.width - (currentScrollPaneWidth + uiOffset) 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) { if (GlRenderer.enabled && GlRenderer.canvasWidth != GameShell.canvasWidth) {
GlRenderer.canvasWidth = GameShell.canvasWidth GlRenderer.canvasWidth = GameShell.canvasWidth
GlRenderer.setViewportBounds(0, 0, GameShell.canvasWidth, GameShell.canvasHeight) GlRenderer.setViewportBounds(0, 0, GameShell.canvasWidth, GameShell.canvasHeight)
@ -296,6 +441,10 @@ class plugin : Plugin() {
accumulatedTime = 0L 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) // Draw synced actions (that require to be done between glBegin and glEnd)
if (drawActions.isNotEmpty()) { if (drawActions.isNotEmpty()) {
synchronized(drawActions) { 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(){ private fun initKondoUI(){
DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2) DrawText(FontType.LARGE, fromColor(Color(16777215)), TextModifier.CENTER, "KondoKit Loading Sprites...", GameShell.canvasWidth/2, GameShell.canvasHeight/2)
if(!allSpritesLoaded()) return; if(!allSpritesLoaded()) return;
@ -379,6 +540,7 @@ class plugin : Plugin() {
// Update component tree UI to apply the new theme // Update component tree UI to apply the new theme
SwingUtilities.updateComponentTreeUI(GameShell.frame) SwingUtilities.updateComponentTreeUI(GameShell.frame)
GameShell.frame.background = Color.BLACK
} catch (e : Exception) { } catch (e : Exception) {
e.printStackTrace() e.printStackTrace()
} }