From bed52d968e5834cf6abc81c8f4890e3fe5e89162 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Thu, 2 Oct 2025 04:17:13 -0700 Subject: [PATCH] Better reflective editor for hels --- .../src/main/kotlin/FooTextPlugin/plugin.kt | 57 ++++++++++-- .../KondoKit/components/SettingsPanel.kt | 90 +++++++++---------- .../KondoKit/views/ReflectiveEditorView.kt | 4 +- 3 files changed, 94 insertions(+), 57 deletions(-) diff --git a/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.kt b/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.kt index d6539f5..be84b59 100644 --- a/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.kt +++ b/plugin-playground/src/main/kotlin/FooTextPlugin/plugin.kt @@ -241,15 +241,52 @@ class plugin : Plugin() { override fun Init() { // Load username matches from local storage - usernameMatches = API.GetData("foo-text-username-matches") as? HashMap ?: HashMap() + val storedData = API.GetData("foo-text-username-matches") + usernameMatches = when (storedData) { + is String -> { + try { + gson.fromJson(storedData, HashMap::class.java) as HashMap + } catch (e: Exception) { + println("Failed to deserialize username matches: ${e.message}") + HashMap() + } + } + is HashMap<*, *> -> { + // Old format: Direct HashMap (for backward compatibility) + try { + @Suppress("UNCHECKED_CAST") + storedData as HashMap + } catch (e: Exception) { + println("Failed to cast username matches: ${e.message}") + HashMap() + } + } + else -> { + // No data or unexpected format + HashMap() + } + } } fun OnKondoValueUpdated() { + println("OnKondoValueUpdated called - current usernameMatches: $usernameMatches") StoreData() + OnPluginsReloaded() //refresh the ui + } + + fun getCleanUserName(): String { + return Player.usernameInput.toString().replace(" ", "_") + } + + override fun OnPluginsReloaded(): Boolean { + grabConfig() + return true } private fun StoreData() { - API.StoreData("foo-text-username-matches", usernameMatches) + val jsonString = gson.toJson(usernameMatches) + println("Storing ${jsonString}") + API.StoreData("foo-text-username-matches", jsonString) } override fun Draw(timeDelta: Long) { @@ -268,7 +305,7 @@ class plugin : Plugin() { private fun fetchAccountTypeFromAPI(){ println("Fetching Iron status from API...") - val cleanUsername = Player.usernameInput.toString().replace(" ", "_") + val cleanUsername = getCleanUserName() val apiUrl = "http://api.2009scape.org:3000/hiscores/playerSkills/1/${cleanUsername.toLowerCase()}" Thread { try { @@ -302,15 +339,19 @@ class plugin : Plugin() { } override fun OnLogin() { + grabConfig() + } + + private fun grabConfig() { // Check if we already have the account type for this user - val cleanUsername = Player.usernameInput.toString().toLowerCase().replace(" ", "_") - if (usernameMatches.containsKey(cleanUsername)) { + val cleanUsername = getCleanUserName() + if (usernameMatches.containsKey(cleanUsername.toLowerCase())) { ACCOUNT_TYPE = usernameMatches[cleanUsername]!! println("Using cached account type: $ACCOUNT_TYPE for $cleanUsername") return } - - // The server doesn't tell us what account type we are. + + // The game server doesn't tell us what account type we are. // Requesting from API is the easier way to tell. fetchAccountTypeFromAPI() } @@ -322,7 +363,7 @@ class plugin : Plugin() { if (colonIndex != -1) { val suffix = text.substring(colonIndex) // modify and add the rest (username is always before the first ':' ) - val newText = "${TYPE_ICONS[ACCOUNT_TYPE]}$username$BUBBLE_ICON$suffix" + val newText = "${TYPE_ICONS.getOrDefault(ACCOUNT_TYPE, "")}$username$BUBBLE_ICON$suffix" return encodeToJagStr(newText) } return encodeToJagStr(text) diff --git a/plugin-playground/src/main/kotlin/KondoKit/components/SettingsPanel.kt b/plugin-playground/src/main/kotlin/KondoKit/components/SettingsPanel.kt index ca0d461..9f6a5d2 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/components/SettingsPanel.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/components/SettingsPanel.kt @@ -340,48 +340,43 @@ class SettingsPanel(private val plugin: Plugin) : JPanel() { maximumSize = Dimension(120, 30) addActionListener { try { - // Create a new HashMap from the table data - // We need to determine the key and value types from the field's generic type - val newHashMap = HashMap() + // Commit any active cell editing before reading values + if (table.isEditing) { + table.cellEditor.stopCellEditing() + } + + // Get the current HashMap from the field and modify it in place + val currentHashMap = field.get(plugin) as? HashMap ?: HashMap() + + // Clear the current HashMap + currentHashMap.clear() + + // Add the new entries from the table to the existing HashMap for (i in 0 until tableModel.rowCount) { val key = tableModel.getValueAt(i, 0).toString() val value = tableModel.getValueAt(i, 1).toString() // Only add non-empty keys - if (key.isNotBlank()) { - // Skip empty values - if (value.isBlank()) { - Helpers.showToast( - this@SettingsPanel, - "Skipping entry with empty value for key '$key'", - JOptionPane.WARNING_MESSAGE - ) - continue - } - - // Try to convert the value to the appropriate type based on the field's generic type - val convertedValue = try { - // For HashMap which is what FooTextPlugin uses - if (field.genericType.toString().contains("java.util.HashMap") || - field.genericType.toString().contains("HashMap") || - field.genericType.toString().contains("HashMap")) { + if (key.isNotBlank()) { + // Skip empty values + if (value.isBlank()) { + Helpers.showToast( + this@SettingsPanel, + "Skipping entry with empty value for key '$key'", + JOptionPane.WARNING_MESSAGE + ) + continue + } + + // Try to convert the value to the appropriate type based on the field's generic type + val convertedValue = try { + // For HashMap - treat all HashMap fields the same way regardless of plugin + val fieldTypeName = field.genericType.toString() + if (fieldTypeName.contains("java.util.HashMap") || + fieldTypeName.contains("HashMap") || + fieldTypeName.contains("HashMap")) { try { val intValue = value.toInt() - // For FooTextPlugin, account types should be 0-3 - if (field.declaringClass.simpleName == "plugin" && - field.declaringClass.`package`.name.contains("FooTextPlugin")) { - if (intValue < 0 || intValue > 3) { - Helpers.showToast( - this@SettingsPanel, - "Account type for '$key' should be 0-3. Using 0 as default.", - JOptionPane.WARNING_MESSAGE - ) - 0 - } else { - intValue - } - } else { - intValue - } + intValue } catch (e: NumberFormatException) { Helpers.showToast( this@SettingsPanel, @@ -392,20 +387,20 @@ class SettingsPanel(private val plugin: Plugin) : JPanel() { } } // For other numeric types - else if (field.genericType.toString().contains("java.lang.Integer") || - field.genericType.toString().contains("int")) { + else if (fieldTypeName.contains("java.lang.Integer") || + fieldTypeName.contains("int")) { value.toInt() } - else if (field.genericType.toString().contains("java.lang.Double") || - field.genericType.toString().contains("double")) { + else if (fieldTypeName.contains("java.lang.Double") || + fieldTypeName.contains("double")) { value.toDouble() } - else if (field.genericType.toString().contains("java.lang.Float") || - field.genericType.toString().contains("float")) { + else if (fieldTypeName.contains("java.lang.Float") || + fieldTypeName.contains("float")) { value.toFloat() } - else if (field.genericType.toString().contains("java.lang.Boolean") || - field.genericType.toString().contains("boolean")) { + else if (fieldTypeName.contains("java.lang.Boolean") || + fieldTypeName.contains("boolean")) { value.toBoolean() } // Default to string for other types @@ -416,12 +411,13 @@ class SettingsPanel(private val plugin: Plugin) : JPanel() { // If conversion fails, keep as string value } - newHashMap[key] = convertedValue + currentHashMap[key] = convertedValue } } - // Update the field with the new HashMap - fieldNotifier.setFieldValue(field, newHashMap) + // Update the field to trigger notifications (even though the reference is the same) + // This ensures OnKondoValueUpdated() gets called if it exists + fieldNotifier.setFieldValue(field, currentHashMap) Helpers.showToast( this@SettingsPanel, "${field.name} updated successfully!" diff --git a/plugin-playground/src/main/kotlin/KondoKit/views/ReflectiveEditorView.kt b/plugin-playground/src/main/kotlin/KondoKit/views/ReflectiveEditorView.kt index b2b82ae..535d0dd 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/views/ReflectiveEditorView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/views/ReflectiveEditorView.kt @@ -952,7 +952,7 @@ object ReflectiveEditorView : View { for ((_, plugin) in loadedPlugins) { val pluginName = getPluginDirName(plugin as Plugin) loadedPluginNames.add(pluginName) - System.out.println("Loaded plugin: $pluginName") + //System.out.println("Loaded plugin: $pluginName") } } catch (e: Exception) { e.printStackTrace() @@ -1128,7 +1128,7 @@ object ReflectiveEditorView : View { val isDisabled = disabledPluginInfo.containsKey(pluginName) val disabledVersion = disabledPluginInfo[pluginName] - System.out.println("Processing plugin: $pluginName, isLoaded: $isLoaded, isDisabled: $isDisabled, disabledVersion: $disabledVersion") + //System.out.println("Processing plugin: $pluginName, isLoaded: $isLoaded, isDisabled: $isDisabled, disabledVersion: $disabledVersion") // Check if this plugin is currently being downloaded val existingStatus = pluginStatuses.find { it.name == pluginName }