package KondoKit import rt4.GameShell import java.awt.* import java.awt.event.MouseListener import java.lang.reflect.Field import java.lang.reflect.ParameterizedType import java.lang.reflect.Type import java.util.* import java.util.Timer import javax.swing.* object Helpers { fun convertValue(type: Class<*>, genericType: Type?, value: String): Any { return when { type == Int::class.java -> value.toInt() type == Double::class.java -> value.toDouble() type == Boolean::class.java -> value.toBoolean() type == Color::class.java -> convertToColor(value) type == List::class.java && genericType is ParameterizedType -> { val actualTypeArgument = genericType.actualTypeArguments.firstOrNull() when { value.isBlank() -> emptyList() // Handle empty string by returning an empty list actualTypeArgument == Int::class.javaObjectType -> value.trim('[', ']').split(",").filter { it.isNotBlank() }.map { it.trim().toInt() } actualTypeArgument == String::class.java -> value.trim('[', ']').split(",").filter { it.isNotBlank() }.map { it.trim() } else -> throw IllegalArgumentException("Unsupported List type: $actualTypeArgument") } } else -> value // Default to String } } fun showToast( parentComponent: Component?, message: String, messageType: Int = JOptionPane.INFORMATION_MESSAGE ) { SwingUtilities.invokeLater { val toast = JWindow() toast.type = Window.Type.POPUP toast.background = Color(0, 0, 0, 0) val panel = JPanel() panel.isOpaque = false panel.layout = BoxLayout(panel, BoxLayout.Y_AXIS) val label = JLabel(message) label.foreground = Color.WHITE label.background = when (messageType) { JOptionPane.ERROR_MESSAGE -> Color(220, 20, 60, 230) // Crimson for errors JOptionPane.INFORMATION_MESSAGE -> Color(0, 128, 0, 230) // Green for success JOptionPane.WARNING_MESSAGE -> Color(255, 165, 0, 230) // Orange for warnings else -> Color(0, 0, 0, 170) // Default semi-transparent black } label.isOpaque = true label.border = BorderFactory.createEmptyBorder(10, 20, 10, 20) label.maximumSize = Dimension(242, 50) label.preferredSize = Dimension(242, 50) panel.add(label) toast.contentPane.add(panel) toast.pack() // Adjust for parent component location if it exists if (parentComponent != null && GameShell.canvas.isShowing) { val parentLocation = parentComponent.locationOnScreen val x = parentLocation.x val y = GameShell.canvas.locationOnScreen.y toast.setLocation(x, y) } else { // Fallback to screen center if no parent is provided val screenSize = Toolkit.getDefaultToolkit().screenSize val x = (screenSize.width - toast.width) / 2 val y = screenSize.height - toast.height - 50 toast.setLocation(x, y) } toast.isVisible = true Timer().schedule(object : TimerTask() { override fun run() { SwingUtilities.invokeLater { toast.isVisible = false toast.dispose() } } }, 2000) } } private fun convertToColor(value: String): Color { return Color.decode(value) } fun colorToHex(color: Color): String { return "#%02x%02x%02x".format(color.red, color.green, color.blue) } fun colorToIntArray(color: Color): IntArray { return intArrayOf(color.red, color.green, color.blue) } interface FieldObserver { fun onFieldChange(field: Field, newValue: Any?) } fun addMouseListenerToAll(container: Container, listener: MouseListener) { // Recursively go through all components within the container for (component in container.components) { // Add the passed MouseListener to the component if (component is JComponent || component is Canvas) { component.addMouseListener(listener) } // If the component is a container, recursively call this function if (component is Container) { addMouseListenerToAll(component, listener) } } } class FieldNotifier(private val plugin: Any) { private val observers = mutableListOf() private fun notifyFieldChange(field: Field, newValue: Any?) { for (observer in observers) { observer.onFieldChange(field, newValue) } } fun setFieldValue(field: Field, value: Any?) { field.isAccessible = true field.set(plugin, value) notifyFieldChange(field, value) try { val onUpdateMethod = plugin::class.java.getMethod("OnKondoValueUpdated") onUpdateMethod.invoke(plugin) } catch (e: NoSuchMethodException) { // The method doesn't exist } catch (e: Exception) { e.printStackTrace() } } } fun getSpriteId(skillId: Int) : Int { return when (skillId) { 0 -> 197 1 -> 199 2 -> 198 3 -> 203 4 -> 200 5 -> 201 6 -> 202 7 -> 212 8 -> 214 9 -> 208 10 -> 211 11 -> 213 12 -> 207 13 -> 210 14 -> 209 15 -> 205 16 -> 204 17 -> 206 18 -> 216 19 -> 217 20 -> 215 21 -> 220 22 -> 221 23 -> 222 else -> 222 } } fun showAlert(message: String, title: String, type: Int){ JOptionPane.showMessageDialog(null, message, title, type) } fun formatHtmlLabelText(text1: String, color1: Color, text2: String, color2: Color): String { return "
" + "$text1" + "$text2" + "
" } fun formatNumber(value: Int): String { return when { value >= 1_000_000 -> String.format("%.2fM", value / 1_000_000.0) value >= 1_000 -> String.format("%.2fK", value / 1_000.0) else -> value.toString() } } fun getProgressBarColor(skillId: Int): Color { // Straight from runelite return when (skillId) { 0 -> Color(155, 32, 7) // ATTACK 1 -> Color(98, 119, 190) // DEFENCE 2 -> Color(4, 149, 90) // STRENGTH 3 -> Color(131, 126, 126) // HITPOINTS 4 -> Color(109, 144, 23) // RANGED 5 -> Color(159, 147, 35) // PRAYER 6 -> Color(50, 80, 193) // MAGIC 7 -> Color(112, 35, 134) // COOKING 8 -> Color(52, 140, 37) // WOODCUTTING 9 -> Color(3, 141, 125) // FLETCHING 10 -> Color(106, 132, 164) // FISHING 11 -> Color(189, 120, 25) // FIREMAKING 12 -> Color(151, 110, 77) // CRAFTING 13 -> Color(108, 107, 82) // SMITHING 14 -> Color(93, 143, 167) // MINING 15 -> Color(7, 133, 9) // HERBLORE 16 -> Color(58, 60, 137) // AGILITY 17 -> Color(108, 52, 87) // THIEVING 18 -> Color(100, 100, 100) // SLAYER 19 -> Color(101, 152, 63) // FARMING 20 -> Color(170, 141, 26) // RUNECRAFT 21 -> Color(92, 89, 65) // HUNTER 22 -> Color(130, 116, 95) // CONSTRUCTION 23 -> Color(150, 50, 50) // Placeholder for any additional skill else -> Color(128, 128, 128) // Default grey for unhandled skill IDs } } }