Better reflective editor for hels

This commit is contained in:
downthecrop 2025-10-02 04:17:13 -07:00
parent b61f4da214
commit bed52d968e
3 changed files with 94 additions and 57 deletions

View file

@ -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<String, Int> ?: HashMap()
val storedData = API.GetData("foo-text-username-matches")
usernameMatches = when (storedData) {
is String -> {
try {
gson.fromJson(storedData, HashMap::class.java) as HashMap<String, Int>
} 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<String, Int>
} 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)

View file

@ -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<Any, Any>()
// 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<Any, Any> ?: HashMap<Any, Any>()
// 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<String, Int> which is what FooTextPlugin uses
if (field.genericType.toString().contains("java.util.HashMap<java.lang.String, java.lang.Integer>") ||
field.genericType.toString().contains("HashMap<String, Int>") ||
field.genericType.toString().contains("HashMap<String, Integer>")) {
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<String, Int> - treat all HashMap<String, Int> fields the same way regardless of plugin
val fieldTypeName = field.genericType.toString()
if (fieldTypeName.contains("java.util.HashMap<java.lang.String, java.lang.Integer>") ||
fieldTypeName.contains("HashMap<String, Int>") ||
fieldTypeName.contains("HashMap<String, Integer>")) {
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!"

View file

@ -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 }