mirror of
https://gitlab.com/2009scape/rt4-client.git
synced 2025-12-09 16:45:46 -07:00
Compare commits
28 commits
083d0c558d
...
7594e98f51
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7594e98f51 | ||
|
|
1de6638a12 | ||
|
|
4ebba194dc | ||
|
|
e05f5829d7 | ||
|
|
cf5ccbf1ac | ||
|
|
cb9758f7d5 | ||
|
|
1cca6611ee | ||
|
|
52d07d5795 | ||
|
|
f2d4c17569 | ||
|
|
c24df5ab46 | ||
|
|
07f4dc9349 | ||
|
|
c307db1e11 | ||
|
|
8b89a2bb8c | ||
|
|
c5ba4ecc94 | ||
|
|
341d6758c1 | ||
|
|
1f1718d917 | ||
|
|
8180e20281 | ||
|
|
e7f46f1006 | ||
|
|
83fe4805ac | ||
|
|
71afb2b385 | ||
|
|
15deb6216f | ||
|
|
4f8bf464c5 | ||
|
|
b3c2adc51f | ||
|
|
838acc57ff | ||
|
|
1eb7483d35 | ||
|
|
af4dafee89 | ||
|
|
8e554b573c | ||
|
|
668345b81e |
14 changed files with 602 additions and 299 deletions
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -160,6 +160,11 @@ public class PluginRepository {
|
|||
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) {
|
||||
loadedPlugins.values().forEach((plugin) -> plugin.NPCOverheadDraw(npc, screenX, screenY));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,6 +25,11 @@ public final class GlRenderer {
|
|||
public static float hFOV = 0;
|
||||
|
||||
|
||||
|
||||
private static ByteBuffer pixelByteBuffer;
|
||||
private static IntBuffer pixelIntBuffer;
|
||||
public static int[] pixelData;
|
||||
|
||||
@OriginalMember(owner = "client!tf", name = "c", descriptor = "F")
|
||||
private static float aFloat30;
|
||||
|
||||
|
|
@ -200,10 +206,34 @@ public final class GlRenderer {
|
|||
public static void swapBuffers() {
|
||||
try {
|
||||
drawable.swapBuffers();
|
||||
readPixels();
|
||||
} catch (@Pc(3) Exception local3) {
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
public static void setFogEnabled(@OriginalArg(0) boolean enabled) {
|
||||
if (enabled == fogEnabled) {
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
166
plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt
Normal file
166
plugin-playground/src/main/kotlin/KondoKit/AltCanvas.kt
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
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 { it.keyPressed(e) }
|
||||
override fun keyReleased(e: KeyEvent) = relayKeyEvent { it.keyReleased(e) }
|
||||
override fun keyTyped(e: KeyEvent) = relayKeyEvent { it.keyTyped(e) }
|
||||
})
|
||||
|
||||
addMouseWheelListener(MouseWheelListener { e -> relayMouseWheelEvent(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(action: (KeyListener) -> Unit) {
|
||||
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()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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<FieldObserver>()
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -77,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
|
||||
|
|
@ -112,8 +110,10 @@ object HiscoresView {
|
|||
} else {
|
||||
text += e.keyChar
|
||||
}
|
||||
SwingUtilities.invokeLater {
|
||||
repaint()
|
||||
}
|
||||
}
|
||||
override fun keyPressed(e: KeyEvent) {
|
||||
if (e.isControlDown) {
|
||||
when (e.keyCode) {
|
||||
|
|
@ -125,26 +125,32 @@ object HiscoresView {
|
|||
val clipboard = Toolkit.getDefaultToolkit().systemClipboard
|
||||
val pasteText = clipboard.getData(DataFlavor.stringFlavor) as String
|
||||
text += pasteText
|
||||
SwingUtilities.invokeLater {
|
||||
repaint()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseClicked(e: MouseEvent) {
|
||||
if (e.x > width - 20 && e.y < 20) {
|
||||
text = ""
|
||||
SwingUtilities.invokeLater {
|
||||
repaint()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Timer(500) {
|
||||
cursorVisible = !cursorVisible
|
||||
if(focusedView == VIEW_NAME)
|
||||
SwingUtilities.invokeLater {
|
||||
repaint()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
|
|
@ -235,7 +241,7 @@ object HiscoresView {
|
|||
playerNameLabel?.revalidate()
|
||||
playerNameLabel?.repaint()
|
||||
|
||||
if(data == null) return;
|
||||
if(data == null) return
|
||||
|
||||
playerNameLabel?.removeAll()
|
||||
|
||||
|
|
@ -319,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) {
|
||||
|
|
@ -437,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
|
||||
|
|
@ -486,7 +488,7 @@ object HiscoresView {
|
|||
hiscorePanel.add(totalCombatPanel)
|
||||
hiscorePanel.add(Box.createVerticalStrut(10))
|
||||
|
||||
hiScoreView = hiscorePanel;
|
||||
hiScoreView = hiscorePanel
|
||||
}
|
||||
|
||||
data class HiscoresResponse(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -33,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<Int, GroundSnapshot>()
|
||||
var gePriceMap = loadGEPrices()
|
||||
const val VIEW_NAME = "LOOT_TRACKER_VIEW";
|
||||
const val VIEW_NAME = "LOOT_TRACKER_VIEW"
|
||||
private val lootItemPanels = mutableMapOf<String, MutableMap<Int, Int>>()
|
||||
private val npcKillCounts = mutableMapOf<String, Int>()
|
||||
private var totalTrackerWidget: XPWidget? = null
|
||||
var lastConfirmedKillNpcId = -1
|
||||
var customToolTipWindow: JWindow? = null
|
||||
private var customToolTipWindow: JWindow? = null
|
||||
var lootTrackerView: JPanel? = null
|
||||
|
||||
fun loadGEPrices(): Map<String, String> {
|
||||
|
|
@ -284,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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import kotlin.math.ceil
|
|||
|
||||
object ReflectiveEditorView {
|
||||
var reflectiveEditorView: JPanel? = null
|
||||
val loadedPlugins: MutableList<String> = mutableListOf()
|
||||
private val loadedPlugins: MutableList<String> = 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -83,6 +84,7 @@ class ScrollablePanel(private val content: JPanel) : JPanel() {
|
|||
}
|
||||
|
||||
private fun handleResize() {
|
||||
SwingUtilities.invokeLater{
|
||||
// Ensure the ScrollablePanel resizes with the frame
|
||||
bounds = Rectangle(0, 0, 242, frame.height)
|
||||
|
||||
|
|
@ -99,6 +101,7 @@ class ScrollablePanel(private val content: JPanel) : JPanel() {
|
|||
revalidate()
|
||||
repaint()
|
||||
}
|
||||
}
|
||||
|
||||
private fun scrollContent(deltaY: Int) {
|
||||
if (!showScrollbar) {
|
||||
|
|
@ -106,7 +109,7 @@ class ScrollablePanel(private val content: JPanel) : JPanel() {
|
|||
content.setLocation(0, currentOffsetY)
|
||||
return
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater {
|
||||
currentOffsetY += deltaY
|
||||
|
||||
// Apply buffer to maxOffset
|
||||
|
|
@ -120,11 +123,12 @@ class ScrollablePanel(private val content: JPanel) : JPanel() {
|
|||
val scrollableRatio = viewHeight.toDouble() / contentHeight
|
||||
scrollbarY = ((-currentOffsetY / contentHeight.toDouble()) * viewHeight).toInt()
|
||||
scrollbarHeight = (viewHeight * scrollableRatio).toInt().coerceAtLeast(20)
|
||||
|
||||
repaint()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateScrollbar() {
|
||||
SwingUtilities.invokeLater {
|
||||
showScrollbar = content.height > frame.height
|
||||
|
||||
val contentHeight = content.height
|
||||
|
|
@ -138,9 +142,9 @@ class ScrollablePanel(private val content: JPanel) : JPanel() {
|
|||
scrollbarY = 0
|
||||
scrollbarHeight = 0
|
||||
}
|
||||
|
||||
repaint()
|
||||
}
|
||||
}
|
||||
|
||||
override fun paintComponent(g: Graphics) {
|
||||
super.paintComponent(g)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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<Int> = mutableListOf()
|
||||
|
||||
|
|
|
|||
|
|
@ -34,14 +34,14 @@ import plugin.Plugin
|
|||
import plugin.api.*
|
||||
import plugin.api.API.*
|
||||
import plugin.api.FontColor.fromColor
|
||||
import rt4.GameShell
|
||||
import rt4.*
|
||||
import rt4.DisplayMode
|
||||
import rt4.GameShell.canvas
|
||||
import rt4.GameShell.frame
|
||||
import rt4.GlRenderer
|
||||
import rt4.InterfaceList
|
||||
import rt4.Player
|
||||
import rt4.client.js5Archive8
|
||||
import rt4.client.mainLoadState
|
||||
import java.awt.*
|
||||
import java.awt.Font
|
||||
import java.awt.event.ActionListener
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
|
|
@ -91,7 +91,11 @@ 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
|
||||
|
||||
private const val FIXED_WIDTH = 765
|
||||
@Exposed("Stretched/Scaled Fixed Mode Support")
|
||||
var useScaledFixed = false
|
||||
|
||||
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
|
||||
|
|
@ -103,14 +107,16 @@ 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 = ""
|
||||
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>()
|
||||
|
||||
fun registerDrawAction(action: () -> Unit) {
|
||||
|
|
@ -120,24 +126,11 @@ class plugin : Plugin() {
|
|||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
|
|
@ -149,55 +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 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 - (FIXED_WIDTH + uiOffset + currentScrollPaneWidth)
|
||||
GameShell.leftMargin = difference / 2
|
||||
}
|
||||
WindowMode.RESIZABLE -> {
|
||||
GameShell.canvasWidth = frame.width - (currentScrollPaneWidth + uiOffset)
|
||||
}
|
||||
}
|
||||
rightPanelWrapper?.preferredSize = Dimension(currentScrollPaneWidth, frame.height)
|
||||
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)
|
||||
if(lastUIOffset != uiOffset){
|
||||
UpdateDisplaySettings()
|
||||
reloadInterfaces = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun OnMiniMenuCreate(currentEntries: Array<out MiniMenuEntry>?) {
|
||||
if (currentEntries != null) {
|
||||
for ((index, entry) in currentEntries.withIndex()) {
|
||||
|
|
@ -218,28 +162,13 @@ 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()
|
||||
|
||||
updateDisplaySettings()
|
||||
frame.remove(rightPanelWrapper)
|
||||
frame.layout = BorderLayout()
|
||||
frame.add(rightPanelWrapper, BorderLayout.EAST)
|
||||
|
||||
rightPanelWrapper?.let { frame.add(it, BorderLayout.EAST) }
|
||||
frame.revalidate()
|
||||
frame.repaint()
|
||||
pluginsReloaded = true
|
||||
reloadInterfaces = true
|
||||
return true
|
||||
|
|
@ -250,9 +179,7 @@ class plugin : Plugin() {
|
|||
initialXP[skillId] = xp
|
||||
return
|
||||
}
|
||||
|
||||
var xpWidget = xpWidgets[skillId]
|
||||
|
||||
if (xpWidget != null) {
|
||||
updateWidget(xpWidget, xp)
|
||||
} else {
|
||||
|
|
@ -265,9 +192,10 @@ class plugin : Plugin() {
|
|||
xpTrackerView?.add(wrappedWidget(xpWidget.container))
|
||||
xpTrackerView?.add(Box.createVerticalStrut(5))
|
||||
|
||||
if(focusedView == XPTrackerView.VIEW_NAME) {
|
||||
xpTrackerView?.revalidate()
|
||||
if(focusedView == XPTrackerView.VIEW_NAME)
|
||||
xpTrackerView?.repaint()
|
||||
}
|
||||
|
||||
updateWidget(xpWidget, xp)
|
||||
}
|
||||
|
|
@ -290,7 +218,7 @@ class plugin : Plugin() {
|
|||
}
|
||||
|
||||
accumulatedTime += timeDelta
|
||||
if (accumulatedTime >= tickInterval) {
|
||||
if (accumulatedTime >= TICK_INTERVAL) {
|
||||
lootTrackerView?.let { onPostClientTick(it) }
|
||||
accumulatedTime = 0L
|
||||
}
|
||||
|
|
@ -312,18 +240,373 @@ 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 first.",
|
||||
"Error",
|
||||
JOptionPane.INFORMATION_MESSAGE
|
||||
)
|
||||
return
|
||||
}
|
||||
if(!useScaledFixed) return
|
||||
if(GetWindowMode() == WindowMode.FIXED){
|
||||
moveAltCanvasToFront()
|
||||
} else {
|
||||
moveCanvasToFront()
|
||||
}
|
||||
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 {
|
||||
val difference = frame.width - (FIXED_WIDTH + uiOffset + currentScrollPaneWidth)
|
||||
GameShell.leftMargin = difference / 2
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
frame.setComponentZOrder(altCanvas, 1)
|
||||
frame.setComponentZOrder(rightPanelWrapper, 0)
|
||||
}
|
||||
|
||||
private fun moveCanvasToFront(){
|
||||
if(altCanvas == null) return
|
||||
frame.setComponentZOrder(altCanvas, 2)
|
||||
frame.setComponentZOrder(canvas, 1)
|
||||
frame.setComponentZOrder(rightPanelWrapper, 0)
|
||||
}
|
||||
|
||||
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
|
||||
useScaledFixed = (GetData("kondoScaledFixed") 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) {
|
||||
|
||||
loadFont()
|
||||
val themeIndex = (GetData("kondoTheme") as? String) ?: "RUNELITE"
|
||||
theme = ThemeType.valueOf(themeIndex)
|
||||
restoreSettings()
|
||||
theme = ThemeType.valueOf(themeName)
|
||||
applyTheme(getTheme(theme))
|
||||
appliedTheme = theme
|
||||
configureLookAndFeel()
|
||||
|
||||
cardLayout = CardLayout()
|
||||
mainContentPanel = JPanel(cardLayout).apply {
|
||||
border = BorderFactory.createEmptyBorder(0, 0, 0, 0) // Removes any default border or padding
|
||||
background = VIEW_BACKGROUND_COLOR
|
||||
preferredSize = Dimension(MAIN_CONTENT_WIDTH, frame.height)
|
||||
isOpaque = true
|
||||
}
|
||||
|
||||
// Register Views
|
||||
createXPTrackerView()
|
||||
createHiscoreSearchView()
|
||||
createLootTrackerView()
|
||||
createReflectiveEditorView()
|
||||
|
||||
mainContentPanel.add(ScrollablePanel(xpTrackerView!!), XPTrackerView.VIEW_NAME)
|
||||
mainContentPanel.add(ScrollablePanel(hiScoreView!!), HiscoresView.VIEW_NAME)
|
||||
mainContentPanel.add(ScrollablePanel(lootTrackerView!!), LootTrackerView.VIEW_NAME)
|
||||
mainContentPanel.add(ScrollablePanel(reflectiveEditorView!!), ReflectiveEditorView.VIEW_NAME)
|
||||
|
||||
val navPanel = Panel().apply {
|
||||
layout = BoxLayout(this, BoxLayout.Y_AXIS)
|
||||
background = WIDGET_COLOR
|
||||
preferredSize = Dimension(NAVBAR_WIDTH, frame.height)
|
||||
}
|
||||
|
||||
navPanel.add(createNavButton(LVL_ICON, XPTrackerView.VIEW_NAME))
|
||||
navPanel.add(createNavButton(MAG_SPRITE, HiscoresView.VIEW_NAME))
|
||||
navPanel.add(createNavButton(LOOT_ICON, LootTrackerView.VIEW_NAME))
|
||||
navPanel.add(createNavButton(WRENCH_ICON, ReflectiveEditorView.VIEW_NAME))
|
||||
|
||||
val rightPanel = Panel(BorderLayout()).apply {
|
||||
add(mainContentPanel, BorderLayout.CENTER)
|
||||
add(navPanel, BorderLayout.EAST)
|
||||
}
|
||||
|
||||
rightPanelWrapper = JScrollPane(rightPanel).apply {
|
||||
preferredSize = Dimension(NAVBAR_WIDTH + MAIN_CONTENT_WIDTH, frame.height)
|
||||
background = VIEW_BACKGROUND_COLOR
|
||||
border = BorderFactory.createEmptyBorder()
|
||||
horizontalScrollBarPolicy = JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
|
||||
verticalScrollBarPolicy = JScrollPane.VERTICAL_SCROLLBAR_NEVER
|
||||
}
|
||||
|
||||
frame.layout = BorderLayout()
|
||||
rightPanelWrapper?.let {
|
||||
frame.add(it, BorderLayout.EAST)
|
||||
}
|
||||
|
||||
if(launchMinimized){
|
||||
setActiveView(HIDDEN_VIEW)
|
||||
} else {
|
||||
setActiveView(XPTrackerView.VIEW_NAME)
|
||||
}
|
||||
if(useScaledFixed) {
|
||||
initAltCanvas()
|
||||
}
|
||||
initialized = true
|
||||
pluginsReloaded = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun setActiveView(viewName: String) {
|
||||
// Handle the visibility of the main content panel
|
||||
if (viewName == HIDDEN_VIEW) {
|
||||
mainContentPanel.isVisible = false
|
||||
} else {
|
||||
if (!mainContentPanel.isVisible) {
|
||||
mainContentPanel.isVisible = true
|
||||
}
|
||||
cardLayout.show(mainContentPanel, viewName)
|
||||
}
|
||||
|
||||
reloadInterfaces = true
|
||||
updateDisplaySettings()
|
||||
|
||||
// Revalidate and repaint necessary panels
|
||||
mainContentPanel.revalidate()
|
||||
rightPanelWrapper?.revalidate()
|
||||
frame?.revalidate()
|
||||
|
||||
mainContentPanel.repaint()
|
||||
rightPanelWrapper?.repaint()
|
||||
frame?.repaint()
|
||||
|
||||
focusedView = viewName
|
||||
}
|
||||
|
||||
private fun createNavButton(spriteId: Int, viewName: String): JPanel {
|
||||
val bufferedImageSprite = getBufferedImageFromSprite(GetSprite(spriteId), NAV_TINT, NAV_GREYSCALE, BOOST)
|
||||
val buttonSize = Dimension(NAVBAR_WIDTH, 32)
|
||||
val imageSize = Dimension((bufferedImageSprite.width / 1.2f).toInt(), (bufferedImageSprite.height / 1.2f).toInt())
|
||||
val cooldownDuration = 100L
|
||||
|
||||
val actionListener = ActionListener {
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (currentTime - lastClickTime < cooldownDuration) {
|
||||
return@ActionListener
|
||||
}
|
||||
lastClickTime = currentTime
|
||||
|
||||
if (focusedView == viewName) {
|
||||
setActiveView("HIDDEN")
|
||||
} else {
|
||||
setActiveView(viewName)
|
||||
}
|
||||
}
|
||||
|
||||
// ImageCanvas with forced size
|
||||
val imageCanvas = ImageCanvas(bufferedImageSprite).apply {
|
||||
background = WIDGET_COLOR
|
||||
preferredSize = imageSize
|
||||
maximumSize = imageSize
|
||||
minimumSize = imageSize
|
||||
}
|
||||
|
||||
// Wrapping the ImageCanvas in another JPanel to prevent stretching
|
||||
val imageCanvasWrapper = JPanel().apply {
|
||||
layout = GridBagLayout() // Keeps the layout of the wrapped panel minimal
|
||||
preferredSize = imageSize
|
||||
maximumSize = imageSize
|
||||
minimumSize = imageSize
|
||||
isOpaque = false // No background for the wrapper
|
||||
add(imageCanvas) // Adding ImageCanvas directly, layout won't stretch it
|
||||
}
|
||||
|
||||
val panelButton = JPanel().apply {
|
||||
layout = GridBagLayout()
|
||||
preferredSize = buttonSize
|
||||
maximumSize = buttonSize
|
||||
minimumSize = buttonSize
|
||||
background = WIDGET_COLOR
|
||||
isOpaque = true
|
||||
|
||||
val gbc = GridBagConstraints().apply {
|
||||
anchor = GridBagConstraints.CENTER
|
||||
fill = GridBagConstraints.NONE // Prevents stretching
|
||||
}
|
||||
|
||||
add(imageCanvasWrapper, gbc)
|
||||
|
||||
// Hover and click behavior
|
||||
val hoverListener = object : MouseAdapter() {
|
||||
override fun mouseEntered(e: MouseEvent?) {
|
||||
background = WIDGET_COLOR.darker()
|
||||
imageCanvas.fillColor = WIDGET_COLOR.darker()
|
||||
imageCanvas.repaint()
|
||||
repaint()
|
||||
}
|
||||
|
||||
override fun mouseExited(e: MouseEvent?) {
|
||||
background = WIDGET_COLOR
|
||||
imageCanvas.fillColor = WIDGET_COLOR
|
||||
imageCanvas.repaint()
|
||||
repaint()
|
||||
}
|
||||
|
||||
override fun mouseClicked(e: MouseEvent?) {
|
||||
actionListener.actionPerformed(null)
|
||||
}
|
||||
}
|
||||
|
||||
addMouseListener(hoverListener)
|
||||
imageCanvas.addMouseListener(hoverListener)
|
||||
}
|
||||
|
||||
return panelButton
|
||||
}
|
||||
|
||||
private fun configureLookAndFeel(){
|
||||
loadFont()
|
||||
try {
|
||||
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel")
|
||||
|
||||
|
|
@ -377,211 +660,14 @@ class plugin : Plugin() {
|
|||
UIManager.put("ToolTip.border", BorderFactory.createLineBorder(TITLE_BAR_COLOR))
|
||||
|
||||
// Update component tree UI to apply the new theme
|
||||
SwingUtilities.updateComponentTreeUI(GameShell.frame)
|
||||
SwingUtilities.updateComponentTreeUI(frame)
|
||||
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
|
||||
|
||||
cardLayout = CardLayout()
|
||||
mainContentPanel = JPanel(cardLayout).apply {
|
||||
border = BorderFactory.createEmptyBorder(0, 0, 0, 0) // Removes any default border or padding
|
||||
background = VIEW_BACKGROUND_COLOR
|
||||
preferredSize = Dimension(MAIN_CONTENT_WIDTH, frame.height)
|
||||
isOpaque = true
|
||||
}
|
||||
|
||||
// Register Views
|
||||
createXPTrackerView()
|
||||
createHiscoreSearchView()
|
||||
createLootTrackerView()
|
||||
createReflectiveEditorView()
|
||||
|
||||
mainContentPanel.add(ScrollablePanel(xpTrackerView!!), XPTrackerView.VIEW_NAME)
|
||||
mainContentPanel.add(ScrollablePanel(hiScoreView!!), HiscoresView.VIEW_NAME)
|
||||
mainContentPanel.add(ScrollablePanel(lootTrackerView!!), LootTrackerView.VIEW_NAME)
|
||||
mainContentPanel.add(ScrollablePanel(reflectiveEditorView!!), ReflectiveEditorView.VIEW_NAME)
|
||||
|
||||
val navPanel = Panel().apply {
|
||||
layout = BoxLayout(this, BoxLayout.Y_AXIS)
|
||||
background = WIDGET_COLOR
|
||||
preferredSize = Dimension(NAVBAR_WIDTH, frame.height)
|
||||
}
|
||||
|
||||
navPanel.add(createNavButton(LVL_ICON, XPTrackerView.VIEW_NAME))
|
||||
navPanel.add(createNavButton(MAG_SPRITE, HiscoresView.VIEW_NAME))
|
||||
navPanel.add(createNavButton(LOOT_ICON, LootTrackerView.VIEW_NAME))
|
||||
navPanel.add(createNavButton(WRENCH_ICON, ReflectiveEditorView.VIEW_NAME))
|
||||
|
||||
var rightPanel = Panel(BorderLayout()).apply {
|
||||
add(mainContentPanel, BorderLayout.CENTER)
|
||||
add(navPanel, BorderLayout.EAST)
|
||||
}
|
||||
|
||||
rightPanelWrapper = JScrollPane(rightPanel).apply {
|
||||
preferredSize = Dimension(NAVBAR_WIDTH + MAIN_CONTENT_WIDTH, frame.height)
|
||||
background = VIEW_BACKGROUND_COLOR
|
||||
border = BorderFactory.createEmptyBorder() // Removes the border completely
|
||||
horizontalScrollBarPolicy = JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
|
||||
verticalScrollBarPolicy = JScrollPane.VERTICAL_SCROLLBAR_NEVER
|
||||
}
|
||||
|
||||
frame.layout = BorderLayout()
|
||||
rightPanelWrapper?.let { frame.add(it, BorderLayout.EAST) }
|
||||
|
||||
if(!launchMinimized){
|
||||
setActiveView(XPTrackerView.VIEW_NAME)
|
||||
} else {
|
||||
setActiveView(HIDDEN_VIEW)
|
||||
}
|
||||
initialized = true
|
||||
pluginsReloaded = true
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
mainContentPanel.isVisible = false
|
||||
} else {
|
||||
if (!mainContentPanel.isVisible) {
|
||||
mainContentPanel.isVisible = true
|
||||
}
|
||||
cardLayout.show(mainContentPanel, viewName)
|
||||
}
|
||||
|
||||
reloadInterfaces = true
|
||||
UpdateDisplaySettings()
|
||||
|
||||
// Revalidate and repaint necessary panels
|
||||
mainContentPanel.revalidate()
|
||||
mainContentPanel.repaint()
|
||||
rightPanelWrapper?.revalidate()
|
||||
rightPanelWrapper?.repaint()
|
||||
frame?.revalidate()
|
||||
frame?.repaint()
|
||||
|
||||
focusedView = viewName
|
||||
}
|
||||
|
||||
private fun createNavButton(spriteId: Int, viewName: String): JPanel {
|
||||
val bufferedImageSprite = getBufferedImageFromSprite(GetSprite(spriteId), NAV_TINT, NAV_GREYSCALE, BOOST)
|
||||
val buttonSize = Dimension(NAVBAR_WIDTH, 32)
|
||||
val imageSize = Dimension((bufferedImageSprite.width / 1.2f).toInt(), (bufferedImageSprite.height / 1.2f).toInt())
|
||||
val cooldownDuration = 100L
|
||||
|
||||
val actionListener = ActionListener {
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (currentTime - lastClickTime < cooldownDuration) {
|
||||
return@ActionListener
|
||||
}
|
||||
lastClickTime = currentTime
|
||||
|
||||
if (focusedView == viewName) {
|
||||
setActiveView("HIDDEN")
|
||||
} else {
|
||||
setActiveView(viewName)
|
||||
}
|
||||
}
|
||||
|
||||
// ImageCanvas with forced size
|
||||
val imageCanvas = ImageCanvas(bufferedImageSprite).apply {
|
||||
background = WIDGET_COLOR
|
||||
preferredSize = imageSize
|
||||
maximumSize = imageSize
|
||||
minimumSize = imageSize
|
||||
}
|
||||
|
||||
// Wrapping the ImageCanvas in another JPanel to prevent stretching
|
||||
val imageCanvasWrapper = JPanel().apply {
|
||||
layout = GridBagLayout() // Keeps the layout of the wrapped panel minimal
|
||||
preferredSize = imageSize
|
||||
maximumSize = imageSize
|
||||
minimumSize = imageSize
|
||||
isOpaque = false // No background for the wrapper
|
||||
add(imageCanvas) // Adding ImageCanvas directly, layout won't stretch it
|
||||
}
|
||||
|
||||
val panelButton = JPanel().apply {
|
||||
layout = GridBagLayout()
|
||||
preferredSize = buttonSize
|
||||
maximumSize = buttonSize
|
||||
minimumSize = buttonSize
|
||||
background = WIDGET_COLOR
|
||||
isOpaque = true // Ensure background is painted
|
||||
|
||||
val gbc = GridBagConstraints().apply {
|
||||
anchor = GridBagConstraints.CENTER
|
||||
fill = GridBagConstraints.NONE // Prevents stretching
|
||||
}
|
||||
|
||||
add(imageCanvasWrapper, gbc)
|
||||
|
||||
// Hover and click behavior
|
||||
val hoverListener = object : MouseAdapter() {
|
||||
override fun mouseEntered(e: MouseEvent?) {
|
||||
background = WIDGET_COLOR.darker()
|
||||
imageCanvas.fillColor = WIDGET_COLOR.darker()
|
||||
imageCanvas.repaint()
|
||||
repaint()
|
||||
}
|
||||
|
||||
override fun mouseExited(e: MouseEvent?) {
|
||||
background = WIDGET_COLOR
|
||||
imageCanvas.fillColor = WIDGET_COLOR
|
||||
imageCanvas.repaint()
|
||||
repaint()
|
||||
}
|
||||
|
||||
override fun mouseClicked(e: MouseEvent?) {
|
||||
actionListener.actionPerformed(null)
|
||||
}
|
||||
}
|
||||
|
||||
addMouseListener(hoverListener)
|
||||
imageCanvas.addMouseListener(hoverListener)
|
||||
}
|
||||
|
||||
return panelButton
|
||||
}
|
||||
|
||||
|
||||
fun loadFont(): Font? {
|
||||
private fun loadFont(): Font? {
|
||||
val fontStream = plugin::class.java.getResourceAsStream("res/runescape_small.ttf")
|
||||
return if (fontStream != null) {
|
||||
try {
|
||||
|
|
@ -603,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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue