mirror of
https://gitlab.com/2009scape/rt4-client.git
synced 2025-12-09 16:45:46 -07:00
375 lines
14 KiB
Kotlin
375 lines
14 KiB
Kotlin
package KondoKit
|
|
|
|
import KondoKit.Constants.COMBAT_LVL_SPRITE
|
|
import KondoKit.Helpers.formatHtmlLabelText
|
|
import KondoKit.Helpers.formatNumber
|
|
import KondoKit.Helpers.getSpriteId
|
|
import KondoKit.HiscoresView.createHiscoreSearchView
|
|
import KondoKit.LootTrackerView.BAG_ICON
|
|
import KondoKit.LootTrackerView.createLootTrackerView
|
|
import KondoKit.LootTrackerView.npcDeathSnapshots
|
|
import KondoKit.LootTrackerView.onPostClientTick
|
|
import KondoKit.LootTrackerView.takeGroundSnapshot
|
|
import KondoKit.ReflectiveEditorView.addPlugins
|
|
import KondoKit.ReflectiveEditorView.createReflectiveEditorView
|
|
import KondoKit.SpriteToBufferedImage.getBufferedImageFromSprite
|
|
import KondoKit.XPTrackerView.createTotalXPWidget
|
|
import KondoKit.XPTrackerView.createXPTrackerView
|
|
import KondoKit.XPTrackerView.createXPWidget
|
|
import KondoKit.XPTrackerView.updateWidget
|
|
import KondoKit.XPTrackerView.wrappedWidget
|
|
import KondoKit.plugin.StateManager.initialXP
|
|
import KondoKit.plugin.StateManager.totalXPWidget
|
|
import KondoKit.plugin.StateManager.xpWidgets
|
|
import plugin.Plugin
|
|
import plugin.api.*
|
|
import plugin.api.API.*
|
|
import plugin.api.FontColor.fromColor
|
|
import rt4.GameShell
|
|
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.event.ActionListener
|
|
import java.awt.event.MouseAdapter
|
|
import java.awt.event.MouseEvent
|
|
import javax.swing.*
|
|
|
|
|
|
class plugin : Plugin() {
|
|
companion object {
|
|
val WIDGET_SIZE = Dimension(270, 55)
|
|
val TOTAL_XP_WIDGET_SIZE = Dimension(270, 30)
|
|
val IMAGE_SIZE = Dimension(20, 20)
|
|
val WIDGET_COLOR = Color(27, 27, 27)
|
|
val VIEW_BACKGROUND_COLOR = Color(37, 37, 37)
|
|
val primaryColor = Color(129, 129, 129) // Color for "XP Gained:"
|
|
val secondaryColor = Color(226, 226, 226) // Color for "0"
|
|
var kondoExposed_useLiveGEPrices = true
|
|
var kondoExposed_playerXPMultiplier = 5
|
|
const val FIXED_WIDTH = 782
|
|
const val SCROLLPANE_WIDTH = 340
|
|
private const val WRENCH_ICON = 907
|
|
private const val LVL_ICON = 898
|
|
private const val LOOT_ICON = 777
|
|
private const val MAG_SPRITE = 1423
|
|
private lateinit var cardLayout: CardLayout
|
|
private lateinit var mainContentPanel: Panel
|
|
private var scrollPane: JScrollPane? = null
|
|
private var hiScoreView: JPanel? = null
|
|
private var reflectiveEditorView: JPanel? = null
|
|
private var lootTrackerView: JPanel? = null
|
|
private var xpTrackerView: JPanel? = null
|
|
private var accumulatedTime = 0L
|
|
private const val tickInterval = 600L
|
|
private var pluginsReloaded = false
|
|
private var loginScreen = 160;
|
|
private var lastLogin = ""
|
|
private var initialized = false;
|
|
}
|
|
|
|
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 OnLogin() {
|
|
if (lastLogin != "" && lastLogin != Player.usernameInput.toString()) {
|
|
// if we logged in with a new character
|
|
// we need to reset the trackers
|
|
xpTrackerView?.removeAll()
|
|
totalXPWidget = createTotalXPWidget()
|
|
xpTrackerView?.add(Box.createVerticalStrut(5))
|
|
xpTrackerView?.add(wrappedWidget(totalXPWidget!!.panel))
|
|
xpTrackerView?.add(Box.createVerticalStrut(5))
|
|
initialXP.clear()
|
|
xpWidgets.clear()
|
|
|
|
xpTrackerView?.revalidate()
|
|
if (StateManager.focusedView == "XP_TRACKER_VIEW")
|
|
xpTrackerView?.repaint()
|
|
}
|
|
lastLogin = Player.usernameInput.toString()
|
|
}
|
|
|
|
private fun UpdateDisplaySettings() {
|
|
val mode = GetWindowMode()
|
|
when (mode) {
|
|
WindowMode.FIXED -> {
|
|
if (frame.width < FIXED_WIDTH + SCROLLPANE_WIDTH) {
|
|
frame.setSize(FIXED_WIDTH + SCROLLPANE_WIDTH, frame.height)
|
|
}
|
|
val difference = frame.width - (FIXED_WIDTH + SCROLLPANE_WIDTH)
|
|
GameShell.leftMargin = difference / 2
|
|
}
|
|
WindowMode.RESIZABLE -> {
|
|
GameShell.canvasWidth -= SCROLLPANE_WIDTH
|
|
}
|
|
}
|
|
scrollPane?.revalidate()
|
|
scrollPane?.repaint()
|
|
}
|
|
|
|
fun OnKondoValueUpdated(){
|
|
StoreData("kondoUseRemoteGE", kondoExposed_useLiveGEPrices)
|
|
StoreData("kondoPlayerXPMultiplier", kondoExposed_playerXPMultiplier)
|
|
LootTrackerView.gePriceMap = LootTrackerView.loadGEPrices()
|
|
}
|
|
|
|
override fun OnMiniMenuCreate(currentEntries: Array<out MiniMenuEntry>?) {
|
|
if (currentEntries != null) {
|
|
for ((index, entry) in currentEntries.withIndex()) {
|
|
if (entry.type == MiniMenuType.PLAYER && index == currentEntries.size - 1) {
|
|
val input = entry.subject
|
|
val username = input
|
|
.replace(Regex("<col=[0-9a-fA-F]{6}>"), "")
|
|
.replace(Regex("<img=\\d+>"), "")
|
|
.split(" ") // Split by spaces
|
|
.first() // Take the first part, which is the username
|
|
InsertMiniMenuEntry("Lookup", entry.subject, searchHiscore(username.replace(" ","_")))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun searchHiscore(username: String): Runnable {
|
|
return Runnable {
|
|
cardLayout.show(mainContentPanel, "HISCORE_SEARCH_VIEW")
|
|
StateManager.focusedView = "HISCORE_SEARCH_VIEW"
|
|
val customSearchField = hiScoreView?.let { HiscoresView.CustomSearchField(it) }
|
|
|
|
customSearchField?.searchPlayer(username) ?: run {
|
|
println("searchView is null or CustomSearchField creation failed.")
|
|
}
|
|
hiScoreView?.repaint()
|
|
}
|
|
}
|
|
|
|
|
|
override fun OnPluginsReloaded(): Boolean {
|
|
if (!initialized) return true
|
|
|
|
UpdateDisplaySettings()
|
|
|
|
frame.remove(scrollPane)
|
|
frame.layout = BorderLayout()
|
|
frame.add(scrollPane, BorderLayout.EAST)
|
|
|
|
// Clear or regenerate the reflectiveEditorView
|
|
reflectiveEditorView?.removeAll()
|
|
reflectiveEditorView?.revalidate()
|
|
if(StateManager.focusedView == "REFLECTIVE_EDITOR_VIEW")
|
|
reflectiveEditorView?.repaint()
|
|
|
|
frame.revalidate()
|
|
frame.repaint()
|
|
pluginsReloaded = true
|
|
return true
|
|
}
|
|
|
|
|
|
override fun OnXPUpdate(skillId: Int, xp: Int) {
|
|
if (!initialXP.containsKey(skillId)) {
|
|
initialXP[skillId] = xp
|
|
return
|
|
}
|
|
|
|
var xpWidget = xpWidgets[skillId]
|
|
|
|
if (xpWidget != null) {
|
|
updateWidget(xpWidget, xp)
|
|
} else {
|
|
val previousXp = initialXP[skillId] ?: xp
|
|
if (xp == initialXP[skillId]) return
|
|
|
|
xpWidget = createXPWidget(skillId, previousXp)
|
|
xpWidgets[skillId] = xpWidget
|
|
|
|
xpTrackerView?.add(wrappedWidget(xpWidget.panel))
|
|
xpTrackerView?.add(Box.createVerticalStrut(5))
|
|
|
|
xpTrackerView?.revalidate()
|
|
if(StateManager.focusedView == "XP_TRACKER_VIEW")
|
|
xpTrackerView?.repaint()
|
|
|
|
updateWidget(xpWidget, xp)
|
|
}
|
|
}
|
|
|
|
override fun Draw(timeDelta: Long) {
|
|
if (GlRenderer.enabled && GlRenderer.canvasWidth != GameShell.canvasWidth) {
|
|
GlRenderer.canvasWidth = GameShell.canvasWidth
|
|
GlRenderer.setViewportBounds(0, 0, GameShell.canvasWidth, GameShell.canvasHeight)
|
|
}
|
|
|
|
if (pluginsReloaded) {
|
|
InterfaceList.method3712(true) // Gets the resize working correctly
|
|
reflectiveEditorView?.let { addPlugins(it) }
|
|
pluginsReloaded = false
|
|
}
|
|
|
|
accumulatedTime += timeDelta
|
|
if (accumulatedTime >= tickInterval) {
|
|
lootTrackerView?.let { onPostClientTick(it) }
|
|
accumulatedTime = 0L
|
|
}
|
|
|
|
|
|
// Init in the draw call so we know we are between glBegin and glEnd for HD
|
|
if(!initialized && mainLoadState >= loginScreen) {
|
|
initKondoUI()
|
|
}
|
|
|
|
}
|
|
|
|
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) {
|
|
kondoExposed_useLiveGEPrices = (GetData("kondoUseRemoteGE") as? Boolean) ?: true
|
|
kondoExposed_playerXPMultiplier = (GetData("kondoPlayerXPMultiplier") as? Int) ?: 5
|
|
cardLayout = CardLayout()
|
|
mainContentPanel = Panel(cardLayout)
|
|
mainContentPanel.background = VIEW_BACKGROUND_COLOR
|
|
|
|
xpTrackerView = createXPTrackerView()
|
|
hiScoreView = createHiscoreSearchView()
|
|
lootTrackerView = createLootTrackerView()
|
|
reflectiveEditorView = createReflectiveEditorView()
|
|
mainContentPanel.add(xpTrackerView, "XP_TRACKER_VIEW")
|
|
mainContentPanel.add(hiScoreView, "HISCORE_SEARCH_VIEW")
|
|
mainContentPanel.add(lootTrackerView, "LOOT_TRACKER_VIEW")
|
|
mainContentPanel.add(reflectiveEditorView, "REFLECTIVE_EDITOR_VIEW")
|
|
|
|
val navPanel = Panel().apply {
|
|
layout = BoxLayout(this, BoxLayout.Y_AXIS)
|
|
background = WIDGET_COLOR
|
|
preferredSize = Dimension(42, frame.height)
|
|
}
|
|
|
|
navPanel.add(createNavButton(LVL_ICON, "XP_TRACKER_VIEW"))
|
|
navPanel.add(createNavButton(MAG_SPRITE, "HISCORE_SEARCH_VIEW"))
|
|
navPanel.add(createNavButton(LOOT_ICON, "LOOT_TRACKER_VIEW"))
|
|
navPanel.add(createNavButton(WRENCH_ICON, "REFLECTIVE_EDITOR_VIEW"))
|
|
|
|
val rightPanel = Panel(BorderLayout()).apply {
|
|
add(mainContentPanel, BorderLayout.CENTER)
|
|
add(navPanel, BorderLayout.EAST)
|
|
}
|
|
|
|
scrollPane = JScrollPane(rightPanel).apply {
|
|
preferredSize = Dimension(SCROLLPANE_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()
|
|
scrollPane?.let { frame.add(it, BorderLayout.EAST) }
|
|
|
|
frame.revalidate()
|
|
frame.repaint()
|
|
|
|
StateManager.focusedView = "XP_TRACKER_VIEW"
|
|
initialized = true
|
|
pluginsReloaded = true
|
|
UpdateDisplaySettings()
|
|
}
|
|
}
|
|
|
|
override fun Update() {
|
|
xpWidgets.values.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.panel.repaint()
|
|
}
|
|
|
|
totalXPWidget?.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.panel.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 createNavButton(spriteId: Int, viewName: String): JButton {
|
|
val bufferedImageSprite = getBufferedImageFromSprite(GetSprite(spriteId))
|
|
val buttonSize = Dimension(42, 42)
|
|
val imageSize = Dimension(bufferedImageSprite.width, bufferedImageSprite.height)
|
|
|
|
val actionListener = ActionListener {
|
|
cardLayout.show(mainContentPanel, viewName)
|
|
StateManager.focusedView = viewName
|
|
}
|
|
|
|
val imageCanvas = ImageCanvas(bufferedImageSprite).apply {
|
|
background = WIDGET_COLOR
|
|
preferredSize = imageSize
|
|
maximumSize = imageSize
|
|
minimumSize = imageSize
|
|
addMouseListener(object : MouseAdapter() {
|
|
override fun mouseClicked(e: MouseEvent?) {
|
|
actionListener.actionPerformed(null)
|
|
}
|
|
})
|
|
}
|
|
|
|
val button = JButton().apply {
|
|
layout = GridBagLayout()
|
|
preferredSize = buttonSize
|
|
maximumSize = buttonSize
|
|
minimumSize = buttonSize
|
|
background = WIDGET_COLOR
|
|
isFocusPainted = false
|
|
isBorderPainted = false
|
|
|
|
val gbc = GridBagConstraints().apply {
|
|
anchor = GridBagConstraints.CENTER
|
|
}
|
|
|
|
add(imageCanvas, gbc)
|
|
addActionListener(actionListener)
|
|
}
|
|
|
|
return button
|
|
}
|
|
|
|
object StateManager {
|
|
val initialXP: MutableMap<Int, Int> = HashMap()
|
|
val xpWidgets: MutableMap<Int, XPWidget> = HashMap()
|
|
var totalXPWidget: XPWidget? = null
|
|
var focusedView: String = ""
|
|
}
|
|
}
|